mirror of
https://github.com/Minestom/Minestom.git
synced 2024-06-25 22:14:53 +02:00
195 lines
5.8 KiB
Java
195 lines
5.8 KiB
Java
package net.minestom.server.entity.metadata;
|
|
|
|
import net.kyori.adventure.text.Component;
|
|
import net.minestom.server.entity.Entity;
|
|
import net.minestom.server.entity.Metadata;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.lang.ref.WeakReference;
|
|
import java.util.function.Consumer;
|
|
|
|
public class EntityMeta {
|
|
public static final byte OFFSET = 0;
|
|
public static final byte MAX_OFFSET = OFFSET + 8;
|
|
|
|
private final static byte ON_FIRE_BIT = 0x01;
|
|
private final static byte CROUCHING_BIT = 0x02;
|
|
private final static byte SPRINTING_BIT = 0x08;
|
|
private final static byte SWIMMING_BIT = 0x10;
|
|
private final static byte INVISIBLE_BIT = 0x20;
|
|
private final static byte HAS_GLOWING_EFFECT_BIT = 0x40;
|
|
private final static byte FLYING_WITH_ELYTRA_BIT = (byte) 0x80;
|
|
|
|
private final WeakReference<Entity> entityRef;
|
|
protected final Metadata metadata;
|
|
|
|
public EntityMeta(@Nullable Entity entity, @NotNull Metadata metadata) {
|
|
this.entityRef = new WeakReference<>(entity);
|
|
this.metadata = metadata;
|
|
}
|
|
|
|
/**
|
|
* Sets whether any changes to this meta must result in a metadata packet being sent to entity viewers.
|
|
* By default it's set to true.
|
|
* <p>
|
|
* It's usable if you want to change multiple values of this meta at the same time and want just a
|
|
* single packet being sent: if so, disable notification before your first change and enable it
|
|
* right after the last one: once notification is set to false, we collect all the updates
|
|
* that are being performed, and when it's returned to true we send them all together.
|
|
* An example usage could be found at
|
|
* {@link net.minestom.server.entity.LivingEntity#refreshActiveHand(boolean, boolean, boolean)}.
|
|
*
|
|
* @param notifyAboutChanges if to notify entity viewers about this meta changes.
|
|
*/
|
|
public void setNotifyAboutChanges(boolean notifyAboutChanges) {
|
|
this.metadata.setNotifyAboutChanges(notifyAboutChanges);
|
|
}
|
|
|
|
public boolean isOnFire() {
|
|
return getMaskBit(OFFSET, ON_FIRE_BIT);
|
|
}
|
|
|
|
public void setOnFire(boolean value) {
|
|
setMaskBit(OFFSET, ON_FIRE_BIT, value);
|
|
}
|
|
|
|
public boolean isSneaking() {
|
|
return getMaskBit(OFFSET, CROUCHING_BIT);
|
|
}
|
|
|
|
public void setSneaking(boolean value) {
|
|
setMaskBit(OFFSET, CROUCHING_BIT, value);
|
|
}
|
|
|
|
public boolean isSprinting() {
|
|
return getMaskBit(OFFSET, SPRINTING_BIT);
|
|
}
|
|
|
|
public void setSprinting(boolean value) {
|
|
setMaskBit(OFFSET, SPRINTING_BIT, value);
|
|
}
|
|
|
|
public boolean isSwimming() {
|
|
return getMaskBit(OFFSET, SWIMMING_BIT);
|
|
}
|
|
|
|
public void setSwimming(boolean value) {
|
|
setMaskBit(OFFSET, SWIMMING_BIT, value);
|
|
}
|
|
|
|
public boolean isInvisible() {
|
|
return getMaskBit(OFFSET, INVISIBLE_BIT);
|
|
}
|
|
|
|
public void setInvisible(boolean value) {
|
|
setMaskBit(OFFSET, INVISIBLE_BIT, value);
|
|
}
|
|
|
|
public boolean isHasGlowingEffect() {
|
|
return getMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT);
|
|
}
|
|
|
|
public void setHasGlowingEffect(boolean value) {
|
|
setMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT, value);
|
|
}
|
|
|
|
public boolean isFlyingWithElytra() {
|
|
return getMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT);
|
|
}
|
|
|
|
public void setFlyingWithElytra(boolean value) {
|
|
setMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT, value);
|
|
}
|
|
|
|
public int getAirTicks() {
|
|
return this.metadata.getIndex(OFFSET + 1, 300);
|
|
}
|
|
|
|
public void setAirTicks(int value) {
|
|
this.metadata.setIndex(OFFSET + 1, Metadata.VarInt(value));
|
|
}
|
|
|
|
public Component getCustomName() {
|
|
return this.metadata.getIndex(OFFSET + 2, null);
|
|
}
|
|
|
|
public void setCustomName(Component value) {
|
|
this.metadata.setIndex(OFFSET + 2, Metadata.OptChat(value));
|
|
}
|
|
|
|
public boolean isCustomNameVisible() {
|
|
return this.metadata.getIndex(OFFSET + 3, false);
|
|
}
|
|
|
|
public void setCustomNameVisible(boolean value) {
|
|
this.metadata.setIndex(OFFSET + 3, Metadata.Boolean(value));
|
|
}
|
|
|
|
public boolean isSilent() {
|
|
return this.metadata.getIndex(OFFSET + 4, false);
|
|
}
|
|
|
|
public void setSilent(boolean value) {
|
|
this.metadata.setIndex(OFFSET + 4, Metadata.Boolean(value));
|
|
}
|
|
|
|
public boolean isHasNoGravity() {
|
|
return this.metadata.getIndex(OFFSET + 5, false);
|
|
}
|
|
|
|
public void setHasNoGravity(boolean value) {
|
|
this.metadata.setIndex(OFFSET + 5, Metadata.Boolean(value));
|
|
}
|
|
|
|
public Entity.Pose getPose() {
|
|
return this.metadata.getIndex(OFFSET + 6, Entity.Pose.STANDING);
|
|
}
|
|
|
|
public void setPose(Entity.Pose value) {
|
|
this.metadata.setIndex(OFFSET + 6, Metadata.Pose(value));
|
|
}
|
|
|
|
public int getTickFrozen() {
|
|
return this.metadata.getIndex(OFFSET + 7, 0);
|
|
}
|
|
|
|
public void setTickFrozen(int tickFrozen) {
|
|
this.metadata.setIndex(OFFSET + 7, Metadata.VarInt(tickFrozen));
|
|
}
|
|
|
|
protected byte getMask(int index) {
|
|
return this.metadata.getIndex(index, (byte) 0);
|
|
}
|
|
|
|
protected void setMask(int index, byte mask) {
|
|
this.metadata.setIndex(index, Metadata.Byte(mask));
|
|
}
|
|
|
|
protected boolean getMaskBit(int index, byte bit) {
|
|
return (getMask(index) & bit) == bit;
|
|
}
|
|
|
|
protected void setMaskBit(int index, byte bit, boolean value) {
|
|
byte mask = getMask(index);
|
|
boolean currentValue = (mask & bit) == bit;
|
|
if (currentValue == value) {
|
|
return;
|
|
}
|
|
if (value) {
|
|
mask |= bit;
|
|
} else {
|
|
mask &= ~bit;
|
|
}
|
|
setMask(index, mask);
|
|
}
|
|
|
|
protected void consumeEntity(Consumer<Entity> consumer) {
|
|
Entity entity = this.entityRef.get();
|
|
if (entity != null) {
|
|
consumer.accept(entity);
|
|
}
|
|
}
|
|
|
|
}
|