Introduce changes notification for meta

Introduces a system to avoid spam sending metadata packets by stopping sending, changing the metadata, then sending it all at once
This commit is contained in:
Tofaa 2024-02-06 21:44:02 +04:00
parent ad50de2cae
commit 2d76a9eac8
13 changed files with 792 additions and 258 deletions

View file

@ -5,9 +5,19 @@
</component>
<component name="ChangeListManager">
<list default="true" id="9d5d9b6f-43c8-41a4-bb42-a66ffc96c9b0" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/WorldWrapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/WorldWrapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperPlayer.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperPlayer.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/MetaOffsetConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/MetaOffsetConverter.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/code-gen/src/main/java/me/tofaa/entitylib/codegen/Main.java" beforeDir="false" afterPath="$PROJECT_DIR$/code-gen/src/main/java/me/tofaa/entitylib/codegen/Main.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/code-gen/src/main/resources/offset-calculator.json" beforeDir="false" afterPath="$PROJECT_DIR$/code-gen/src/main/resources/offset-calculator.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/src/main/java/me/tofaa/entitylib/common/AbstractEntityLibAPI.java" beforeDir="false" afterPath="$PROJECT_DIR$/common/src/main/java/me/tofaa/entitylib/common/AbstractEntityLibAPI.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/src/main/java/me/tofaa/entitylib/common/AbstractWorldWrapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/common/src/main/java/me/tofaa/entitylib/common/AbstractWorldWrapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java" beforeDir="false" afterPath="$PROJECT_DIR$/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/test-plugin/src/main/java/me/tofaa/testentitylib/TestEntityLibPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/test-plugin/src/main/java/me/tofaa/testentitylib/TestEntityLibPlugin.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/test-plugin/src/main/resources/plugin.yml" beforeDir="false" afterPath="$PROJECT_DIR$/test-plugin/src/main/resources/plugin.yml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -95,6 +105,7 @@
&quot;Gradle.EntityLib [dependencies].executor&quot;: &quot;Run&quot;,
&quot;Gradle.EntityLib:code-gen [:code-gen:Main.main()].executor&quot;: &quot;Run&quot;,
&quot;Gradle.EntityLib:test-plugin [runServer].executor&quot;: &quot;Run&quot;,
&quot;Gradle.EntityLib:test-plugin [shadowJar].executor&quot;: &quot;Run&quot;,
&quot;Repository.Attach.Annotations&quot;: &quot;false&quot;,
&quot;Repository.Attach.JavaDocs&quot;: &quot;false&quot;,
&quot;Repository.Attach.Sources&quot;: &quot;false&quot;,
@ -230,10 +241,10 @@
<recent_temporary>
<list>
<item itemvalue="Gradle.EntityLib:test-plugin [runServer]" />
<item itemvalue="Gradle.EntityLib:test-plugin [shadowJar]" />
<item itemvalue="Application.Main" />
<item itemvalue="Gradle.EntityLib [dependencies]" />
<item itemvalue="Gradle.PE-EntityMeta [compileTestJava]" />
<item itemvalue="Gradle.EntityLib:test-plugin [shadowJar]" />
</list>
</recent_temporary>
</component>
@ -292,7 +303,8 @@
<workItem from="1706784821835" duration="7882000" />
<workItem from="1706858181164" duration="925000" />
<workItem from="1707159905372" duration="3391000" />
<workItem from="1707210065718" duration="1328000" />
<workItem from="1707210065718" duration="4823000" />
<workItem from="1707219870641" duration="4868000" />
</task>
<servers />
</component>

View file

@ -3,7 +3,9 @@ package me.tofaa.entitylib;
import com.github.retrooper.packetevents.PacketEventsAPI;
import me.tofaa.entitylib.tick.TickContainer;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@ -26,6 +28,26 @@ public interface EntityLibAPI<W, T> {
void onEnable();
/**
* Attempts to search and find an entity across all wrapped worlds. This only works on EntityLib entities.
* @param entityId the entity id of the entity
* @return the entity if one is found, null otherwise.
*/
@Nullable WrapperEntity findEntity(int entityId);
/**
* Mainly internal method to register the {@link WrapperEntity} to EntitLib cache, all {@link WorldWrapper}'s do this automatically
* @param entity
*/
@ApiStatus.Internal
void globalRegisterEntity(@NotNull WrapperEntity entity);
/**
* Mainly internal method to unregister the {@link WrapperEntity} to EntitLib cache, all {@link WorldWrapper}'s do this automatically
* @param entity
*/
void globalUnregisterEntity(@NotNull WrapperEntity entity);
/**
* Creates a wrapped world for the platform specific world.

View file

@ -19,7 +19,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.function.Function;
import static me.tofaa.entitylib.meta.MetaOffsetConverter.EntityMetaOffsets.*;
public class EntityMeta implements EntityMetadataProvider {
@ -65,6 +66,14 @@ public class EntityMeta implements EntityMetadataProvider {
this.metadata = metadata;
}
public void setNotifyAboutChanges(boolean notifyAboutChanges) {
metadata.setNotifyAboutChanges(notifyAboutChanges);
}
public boolean isNotifyingChanges() {
return metadata.isNotifyingChanges();
}
public boolean isOnFire() {
return getMaskBit(OFFSET, ON_FIRE_BIT);
}
@ -122,59 +131,59 @@ public class EntityMeta implements EntityMetadataProvider {
}
public short getAirTicks() {
return this.metadata.getIndex((byte) 1, (short) 300);
return this.metadata.getIndex(airTicksOffset(), (short) 300);
}
public void setAirTicks(short value) {
this.metadata.setIndex((byte) 1, EntityDataTypes.SHORT, value);
this.metadata.setIndex(airTicksOffset(), EntityDataTypes.SHORT, value);
}
public Component getCustomName() {
return this.metadata.getIndex(offset(OFFSET, 2), null);
return this.metadata.getIndex(customNameOffset(), null);
}
public void setCustomName(Component value) {
this.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.ADV_COMPONENT, value);
this.metadata.setIndex(customNameOffset(), EntityDataTypes.ADV_COMPONENT, value);
}
public boolean isCustomNameVisible() {
return this.metadata.getIndex(offset(OFFSET, 3), false);
return this.metadata.getIndex(customNameVisibleOffset(), false);
}
public void setCustomNameVisible(boolean value) {
this.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.BOOLEAN, value);
this.metadata.setIndex(customNameVisibleOffset(), EntityDataTypes.BOOLEAN, value);
}
public boolean isSilent() {
return this.metadata.getIndex((byte) 4, false);
return this.metadata.getIndex(silentOffset(), false);
}
public void setSilent(boolean value) {
this.metadata.setIndex((byte) 4, EntityDataTypes.BOOLEAN, value);
this.metadata.setIndex(silentOffset(), EntityDataTypes.BOOLEAN, value);
}
public boolean isHasNoGravity() {
return this.metadata.getIndex(offset(OFFSET, 5), true);
public boolean hasNoGravity() {
return this.metadata.getIndex(hasNoGravityOffset(), true);
}
public void setHasNoGravity(boolean value) {
this.metadata.setIndex(offset(OFFSET, 5), EntityDataTypes.BOOLEAN, value);
this.metadata.setIndex(hasNoGravityOffset(), EntityDataTypes.BOOLEAN, value);
}
public EntityPose getPose() {
return this.metadata.getIndex(offset(OFFSET, 6), EntityPose.STANDING);
return this.metadata.getIndex(poseOffset(), EntityPose.STANDING);
}
public void setPose(EntityPose value) {
this.metadata.setIndex(offset(OFFSET, 6), EntityDataTypes.ENTITY_POSE, value);
this.metadata.setIndex(poseOffset(), EntityDataTypes.ENTITY_POSE, value);
}
public int getTicksFrozenInPowderedSnow() {
return this.metadata.getIndex(offset(OFFSET, 7), 0);
return this.metadata.getIndex(ticksFrozenInPowderedSnowOffset(), 0);
}
public void setTicksFrozenInPowderedSnow(int value) {
this.metadata.setIndex(offset(OFFSET, 7), EntityDataTypes.INT, value);
this.metadata.setIndex(ticksFrozenInPowderedSnowOffset(), EntityDataTypes.INT, value);
}
public WrapperPlayServerEntityMetadata createPacket() {

View file

@ -10,11 +10,13 @@ import org.jetbrains.annotations.ApiStatus;
@SuppressWarnings("unused")
public final class MetaOffsetConverter {
private MetaOffsetConverter() {
}
public static final class EntityMetaOffsets {
public static byte airTicksOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 47 && protocolVersion <= 47) {
if (protocolVersion >= 47 && protocolVersion <= 765) {
return 1;
}
throw new RuntimeException("Unknown protocol version for this method");
@ -67,7 +69,9 @@ public final class MetaOffsetConverter {
}
throw new RuntimeException("Unknown protocol version for this method");
}
}
public static final class AbstractDisplayMetaOffsets {
public static byte interpolationDelayOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 762 && protocolVersion <= 765) {
@ -223,7 +227,9 @@ public final class MetaOffsetConverter {
}
throw new RuntimeException("Unknown protocol version for this method");
}
}
public static final class BlockDisplayMetaOffsets {
public static byte blockIdOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
@ -234,7 +240,9 @@ public final class MetaOffsetConverter {
}
throw new RuntimeException("Unknown protocol version for this method");
}
}
public static final class ItemDisplayMetaOffsets {
public static byte itemOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
@ -256,4 +264,172 @@ public final class MetaOffsetConverter {
}
throw new RuntimeException("Unknown protocol version for this method");
}
}
public static final class TextDisplayMetaOffsets {
public static byte textOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 26;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 25;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte textColorOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 27;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 26;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte textBackgroundColorOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 28;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 27;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte textBackgroundOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 29;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 28;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte textScaleOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 30;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 29;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte textAlignmentOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 31;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 30;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte lineWidthOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 32;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 31;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte backgroundColorOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 33;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 32;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte textOpacityOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 34;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 33;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte shadowOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 35;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 34;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte seeThroughOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 36;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 35;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte useDefaultBackgroundOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 37;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 36;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte allighnLeftOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 38;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 37;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte allighnRightOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 39;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 38;
}
throw new RuntimeException("Unknown protocol version for this method");
}
public static byte allighnCenterOffset() {
int protocolVersion = getApi().getPacketEvents().getServerManager().getVersion().getProtocolVersion();
if (protocolVersion >= 764 && protocolVersion <= 765) {
return 40;
}
if (protocolVersion >= 762 && protocolVersion <= 763) {
return 39;
}
throw new RuntimeException("Unknown protocol version for this method");
}
}
}

View file

@ -3,38 +3,91 @@ package me.tofaa.entitylib.meta;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unchecked")
public class Metadata {
private final Map<Byte, EntityData> metadataMap = new ConcurrentHashMap<>();
private final int entityId;
private EntityData[] entries = new EntityData[0];
private volatile Map<Integer, EntityData> entryMap = null;
private volatile boolean notifyChanges = true;
private final Map<Byte, EntityData> notNotifiedChanges = new HashMap<>();
public Metadata(int entityId) {
this.entityId = entityId;
}
public <T> T getIndex(byte index, @Nullable T defaultValue) {
EntityData entityData = metadataMap.get(index);
if (entityData == null) return defaultValue;
if (entityData.getValue() == null) return defaultValue;
return (T) entityData.getValue();
final EntityData[] entries = this.entries;
if (index < 0 || index >= entries.length) {
return defaultValue;
}
final EntityData entry = entries[index];
if (entry == null) return defaultValue;
if (entry.getValue() == null) return defaultValue;
return (T) entry.getValue();
}
public <T> void setIndex(byte index, @NotNull EntityDataType<T> dataType, T value) {
EntityData[] entries = this.entries;
if (index >= entries.length) {
final int newLength = Math.max(entries.length * 2, index + 1);
this.entries = entries = Arrays.copyOf(entries, newLength);
}
EntityData data = new EntityData(index, dataType, value);
this.metadataMap.put(index, data);
entries[index] = data;
this.entryMap = null;
final WrapperEntity entity = EntityLib.getApi().findEntity(entityId);
if (entity == null || entity.isSpawned()) return; // Not EntityLib entity then, the user must send the packet manually. OR not spawned.
if (!this.notifyChanges) {
synchronized (this.notNotifiedChanges) {
this.notNotifiedChanges.put(index, data);
}
}
else {
entity.sendPacketToViewers(createPacket());
}
}
public void setNotifyAboutChanges(boolean value) {
if (this.notifyChanges == value) {
return;
}
if (!notifyChanges) {
return; // cache;
}
final WrapperEntity entity = EntityLib.getApi().findEntity(entityId);
if (entity == null || entity.isSpawned()) return;
Map<Byte, EntityData> entries;
synchronized (this.notNotifiedChanges) {
Map<Byte, EntityData> awaitingChanges = this.notNotifiedChanges;
if (awaitingChanges.isEmpty()) return;
entries = Collections.unmodifiableMap(awaitingChanges);
awaitingChanges.clear();
}
entity.sendPacketsToViewers(new WrapperPlayServerEntityMetadata(entityId, new ArrayList<>(entries.values())));
}
public boolean isNotifyingChanges() {
return notifyChanges;
}
@NotNull List<EntityData> getEntries() {
return new ArrayList<>(metadataMap.values());
return Collections.unmodifiableList(Arrays.asList(entries));
}
public WrapperPlayServerEntityMetadata createPacket() {

View file

@ -331,7 +331,7 @@ public class WrapperEntity implements Tickable {
}
public boolean hasNoGravity() {
return entityMeta.isHasNoGravity();
return entityMeta.hasNoGravity();
}
public void setHasNoGravity(boolean hasNoGravity) {

View file

@ -44,6 +44,10 @@ public final class Main {
for (TypeHolder type : types) {
System.out.println("Generating type" + type.className());
TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(type.className() + "Offsets")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC)
.addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build());
for (MetaOffset offset : type.offsets()) {
MethodSpec.Builder method = MethodSpec.methodBuilder(offset.name() + "Offset")
@ -58,10 +62,12 @@ public final class Main {
method.endControlFlow();
}
method.addStatement("throw new RuntimeException(\"Unknown protocol version for this method\")");
baseBuilder.addMethod(method.build());
typeBuilder.addMethod(method.build());
}
baseBuilder.addType(typeBuilder.build());
}
TypeSpec base = baseBuilder.build();
System.out.println("Writing to file");
JavaFile file = JavaFile.builder("me.tofaa.entitylib.meta", base)

View file

@ -6,7 +6,7 @@
"name": "airTicks",
"checks": [
{
"from": 47,
"from": 765,
"to": 47,
"offset": 1
}
@ -74,6 +74,9 @@
}
]
},
{
"class-name": "AbstractDisplayMeta",
"offsets": [
@ -310,7 +313,7 @@
]
},
{
"class-name": "ItemDisplay",
"class-name": "ItemDisplayMeta",
"offsets": [
{
"name": "item",
@ -343,5 +346,236 @@
]
}
]
},
{
"class-name": "TextDisplayMeta",
"offsets": [
{
"name": "text",
"checks": [
{
"from": 765,
"to": 764,
"offset": 26
},
{
"from": 763,
"to": 762,
"offset": 25
}
]
},
{
"name": "textColor",
"checks": [
{
"from": 765,
"to": 764,
"offset": 27
},
{
"from": 763,
"to": 762,
"offset": 26
}
]
},
{
"name": "textBackgroundColor",
"checks": [
{
"from": 765,
"to": 764,
"offset": 28
},
{
"from": 763,
"to": 762,
"offset": 27
}
]
},
{
"name": "textBackground",
"checks": [
{
"from": 765,
"to": 764,
"offset": 29
},
{
"from": 763,
"to": 762,
"offset": 28
}
]
},
{
"name": "textScale",
"checks": [
{
"from": 765,
"to": 764,
"offset": 30
},
{
"from": 763,
"to": 762,
"offset": 29
}
]
},
{
"name": "textAlignment",
"checks": [
{
"from": 765,
"to": 764,
"offset": 31
},
{
"from": 763,
"to": 762,
"offset": 30
}
]
},
{
"name": "lineWidth",
"checks": [
{
"from": 765,
"to": 764,
"offset": 32
},
{
"from": 763,
"to": 762,
"offset": 31
}
]
},
{
"name": "backgroundColor",
"checks": [
{
"from": 765,
"to": 764,
"offset": 33
},
{
"from": 763,
"to": 762,
"offset": 32
}
]
},
{
"name": "textOpacity",
"checks": [
{
"from": 765,
"to": 764,
"offset": 34
},
{
"from": 763,
"to": 762,
"offset": 33
}
]
},
{
"name": "shadow",
"checks": [
{
"from": 765,
"to": 764,
"offset": 35
},
{
"from": 763,
"to": 762,
"offset": 34
}
]
},
{
"name": "seeThrough",
"checks": [
{
"from": 765,
"to": 764,
"offset": 36
},
{
"from": 763,
"to": 762,
"offset": 35
}
]
},
{
"name": "useDefaultBackground",
"checks": [
{
"from": 765,
"to": 764,
"offset": 37
},
{
"from": 763,
"to": 762,
"offset": 36
}
]
},
{
"name": "allighnLeft",
"checks": [
{
"from": 765,
"to": 764,
"offset": 38
},
{
"from": 763,
"to": 762,
"offset": 37
}
]
},
{
"name": "allighnRight",
"checks": [
{
"from": 765,
"to": 764,
"offset": 39
},
{
"from": 763,
"to": 762,
"offset": 38
}
]
},
{
"name": "allighnCenter",
"checks": [
{
"from": 765,
"to": 764,
"offset": 40
},
{
"from": 763,
"to": 762,
"offset": 39
}
]
}
]
}
]

View file

@ -7,11 +7,15 @@ import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.EntityLibAPI;
import me.tofaa.entitylib.Platform;
import me.tofaa.entitylib.tick.TickContainer;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractEntityLibAPI<P, W, T> implements EntityLibAPI<W, T> {
@ -19,6 +23,7 @@ public abstract class AbstractEntityLibAPI<P, W, T> implements EntityLibAPI<W, T
protected final PacketEventsAPI<?> packetEvents;
protected final APIConfig settings;
protected final Collection<TickContainer<?, T>> tickContainers;
protected final Map<Integer, WrapperEntity> globalEntityMap = new ConcurrentHashMap<>();
protected AbstractEntityLibAPI(Platform<P> platform, APIConfig settings) {
this.platform = platform;
@ -27,6 +32,22 @@ public abstract class AbstractEntityLibAPI<P, W, T> implements EntityLibAPI<W, T
this.tickContainers = settings.shouldTickTickables() ? new HashSet<>() : Collections.emptyList();
}
@Override
public @Nullable WrapperEntity findEntity(int entityId) {
return globalEntityMap.get(entityId);
}
@Override
public void globalRegisterEntity(WrapperEntity entity) {
if (globalEntityMap.containsKey(entity.getEntityId())) throw new IllegalArgumentException("Entity with that Id is already registered and present");
globalEntityMap.put(entity.getEntityId(), entity);
}
@Override
public void globalUnregisterEntity(@NotNull WrapperEntity entity) {
globalEntityMap.remove(entity.getEntityId());
}
@NotNull
@Override
public APIConfig getSettings() {

View file

@ -54,6 +54,7 @@ public abstract class AbstractWorldWrapper<W> implements WorldWrapper<W> {
player.spawn(this, location);
entities.put(player.getUuid(), player);
entitiesById.put(player.getEntityId(), player);
EntityLib.getApi().globalRegisterEntity(player);
return player;
}
@ -62,6 +63,7 @@ public abstract class AbstractWorldWrapper<W> implements WorldWrapper<W> {
entity.spawn(this, location);
entities.put(entity.getUuid(), entity);
entitiesById.put(entity.getEntityId(), entity);
EntityLib.getApi().globalRegisterEntity(entity);
return entity;
}
@ -70,6 +72,7 @@ public abstract class AbstractWorldWrapper<W> implements WorldWrapper<W> {
entity.despawn();
this.entities.remove(entity.getUuid());
this.entitiesById.remove(entity.getEntityId());
EntityLib.getApi().globalUnregisterEntity(entity);
}
@Override

View file

@ -25,7 +25,7 @@ public class SpigotEntityLibPlatform extends AbstractPlatform<JavaPlugin> {
@Override
public EntityLibAPI<?, ?> getAPI() {
public SpigotEntityLibAPI getAPI() {
return api;
}

View file

@ -8,20 +8,25 @@ import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.EntityLibAPI;
import me.tofaa.entitylib.WorldWrapper;
import me.tofaa.entitylib.meta.mobs.passive.ChickenMeta;
import me.tofaa.entitylib.spigot.SpigotEntityLibAPI;
import me.tofaa.entitylib.spigot.SpigotEntityLibPlatform;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
public class TestEntityLibPlugin extends JavaPlugin implements Listener {
public class TestEntityLibPlugin extends JavaPlugin implements CommandExecutor {
private EntityLibAPI<World, BukkitTask> api;
private SpigotEntityLibAPI api;
private WrapperEntity e;
private WorldWrapper<World> world;
@ -35,24 +40,27 @@ public class TestEntityLibPlugin extends JavaPlugin implements Listener {
.usePlatformLogger();
EntityLib.init(platform, settings);
api = EntityLib.getApi();
getServer().getPluginManager().registerEvents(this, this);
api = platform.getAPI();
getCommand("testapi").setExecutor(this);
}
@EventHandler
public void onCrouch(PlayerToggleSneakEvent event) {
Player player = event.getPlayer();
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
if (e == null) {
world = api.wrapWorld(player.getWorld());
e = world.spawnEntity(EntityTypes.CHICKEN, SpigotConversionUtil.fromBukkitLocation(player.getLocation()));
e.addViewer(player.getUniqueId());
player.sendMessage("Spawned");
}
world = api.wrapWorld(player.getWorld());
e = world.spawnEntity(EntityTypes.CHICKEN, SpigotConversionUtil.fromBukkitLocation(player.getLocation()));
ChickenMeta meta = (ChickenMeta) e.getEntityMeta();
meta.setBaby(!meta.isBaby());
meta.setHasGlowingEffect(!meta.hasGlowingEffect());
meta.setHasNoGravity(!meta.hasNoGravity());
e.addViewer(player.getUniqueId());
player.sendMessage("Updated");
return true;
}
}

View file

@ -6,15 +6,5 @@ main: me.tofaa.testentitylib.TestEntityLibPlugin
api-version: "1.19"
commands:
testapi:
description: Test PEEntityMeta API
usage: /<command>
testentity:
description: Test PEEntity API
usage: /<command>
testdisplay:
description: Test PEDisplay API
usage: /<command>
spawnclickablefrog:
description: Spawn a clickable frog
description: Test EntityLib API
usage: /<command>