{
/**
* Sets up the API for the platform. This method should be called automatically by the platform. Don't call it yourself.
- * @param settings
*/
void setupApi(@NotNull APIConfig settings);
@@ -83,4 +82,10 @@ public interface Platform
{
@NotNull P getHandle();
+ default void logIfNeeded(String message) {
+ if (getAPI().getSettings().isDebugMode()) {
+ getLogger().info(message);
+ }
+ }
+
}
diff --git a/api/src/main/java/me/tofaa/entitylib/meta/MetaOffsetConverter.java b/api/src/main/java/me/tofaa/entitylib/meta/MetaOffsetConverter.java
index aaae37b..24769ee 100644
--- a/api/src/main/java/me/tofaa/entitylib/meta/MetaOffsetConverter.java
+++ b/api/src/main/java/me/tofaa/entitylib/meta/MetaOffsetConverter.java
@@ -9,9 +9,7 @@
@ApiStatus.Internal
@SuppressWarnings("unused")
public final class MetaOffsetConverter {
- private MetaOffsetConverter() {
-
- }
+ private MetaOffsetConverter() {}
public static final class EntityMetaOffsets {
public static byte airTicksOffset() {
diff --git a/api/src/main/java/me/tofaa/entitylib/storage/ByteEntitySerializer.java b/api/src/main/java/me/tofaa/entitylib/storage/ByteEntitySerializer.java
new file mode 100644
index 0000000..1080e57
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/storage/ByteEntitySerializer.java
@@ -0,0 +1,17 @@
+package me.tofaa.entitylib.storage;
+
+import me.tofaa.entitylib.wrapper.WrapperEntity;
+
+import java.nio.ByteBuffer;
+
+public class ByteEntitySerializer implements EntitySerializer {
+ @Override
+ public WrapperEntity read(ByteBuffer reader) {
+ return null;
+ }
+
+ @Override
+ public void write(ByteBuffer writer, WrapperEntity wrapper) {
+
+ }
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/storage/EntitySerializer.java b/api/src/main/java/me/tofaa/entitylib/storage/EntitySerializer.java
new file mode 100644
index 0000000..07359ca
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/storage/EntitySerializer.java
@@ -0,0 +1,16 @@
+package me.tofaa.entitylib.storage;
+
+import me.tofaa.entitylib.wrapper.WrapperEntity;
+
+/**
+ * An interface that represents a way to serialize and deserialize {@link WrapperEntity} and its subclasses.
+ * @param the reader generic
+ * @param the writer generic
+ */
+public interface EntitySerializer {
+
+ WrapperEntity read(R reader);
+
+ void write(W writer, WrapperEntity wrapper);
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/storage/EntityStorage.java b/api/src/main/java/me/tofaa/entitylib/storage/EntityStorage.java
new file mode 100644
index 0000000..da0fddb
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/storage/EntityStorage.java
@@ -0,0 +1,14 @@
+package me.tofaa.entitylib.storage;
+
+import me.tofaa.entitylib.wrapper.WrapperEntity;
+
+import java.util.Collection;
+
+public interface EntityStorage {
+
+
+ Collection readAll();
+
+ void writeAll(Collection entities);
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/storage/FSEntityStorage.java b/api/src/main/java/me/tofaa/entitylib/storage/FSEntityStorage.java
new file mode 100644
index 0000000..8c10fa8
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/storage/FSEntityStorage.java
@@ -0,0 +1,18 @@
+package me.tofaa.entitylib.storage;
+
+import me.tofaa.entitylib.wrapper.WrapperEntity;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class FSEntityStorage implements EntityStorage{
+ @Override
+ public Collection readAll() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void writeAll(Collection entities) {
+
+ }
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/utils/GithubUpdater.java b/api/src/main/java/me/tofaa/entitylib/utils/GithubUpdater.java
index a15f64f..4d029fc 100644
--- a/api/src/main/java/me/tofaa/entitylib/utils/GithubUpdater.java
+++ b/api/src/main/java/me/tofaa/entitylib/utils/GithubUpdater.java
@@ -23,15 +23,14 @@ public GithubUpdater(String org, String repo, String currentVersion) {
}
@Blocking
- public boolean isLatestVersion() {
+ public boolean isLatestVersion() throws IOException {
String latest = getLatestVersion();
return latest != null && latest.equals(currentVersion);
}
@Blocking
- public String getLatestVersion() {
- try {
+ public String getLatestVersion() throws IOException {
URL url = new URL("https://api.github.com/repos/" + org + "/" + repo + "/releases/latest");
URLConnection connection = url.openConnection();
connection.addRequestProperty("User-Agent", "Mozilla/5.0");
@@ -45,10 +44,6 @@ public String getLatestVersion() {
return json.get("name").getAsString();
}
throw new IOException("Could not find name attribute in github api fetch");
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
}
public String getCurrentVersion() {
diff --git a/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java b/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java
index d42f79e..127688f 100644
--- a/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java
+++ b/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java
@@ -1,9 +1,5 @@
package me.tofaa.entitylib.wrapper;
-import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
-import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
-import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
-import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.world.Location;
@@ -284,7 +280,7 @@ public EntityMeta getEntityMeta() {
return entityMeta;
}
- public UUID getUuid() {
+ public @NotNull UUID getUuid() {
return uuid;
}
diff --git a/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntityAttributes.java b/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntityAttributes.java
new file mode 100644
index 0000000..8c4a1f4
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntityAttributes.java
@@ -0,0 +1,85 @@
+package me.tofaa.entitylib.wrapper;
+
+import com.github.retrooper.packetevents.protocol.attribute.Attribute;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
+import org.w3c.dom.Attr;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
+
+public final class WrapperEntityAttributes {
+
+
+ public static final WrapperPlayServerUpdateAttributes.PropertyModifier.Operation ADDITION = WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION;
+ public static final WrapperPlayServerUpdateAttributes.PropertyModifier.Operation MULTIPLY_BASE = WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_BASE;
+ public static final WrapperPlayServerUpdateAttributes.PropertyModifier.Operation MULTIPLY_TOTAL = WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_TOTAL;
+
+ private final WrapperEntity entity;
+ private final List properties;
+
+ public WrapperEntityAttributes(WrapperEntity entity) {
+ this.entity = entity;
+ this.properties = new CopyOnWriteArrayList<>();
+ }
+
+ public void setAttribute(Attribute attribute, double value, List modifiers) {
+ this.properties.stream()
+ .filter(property -> property.getAttribute() == attribute)
+ .findFirst().ifPresent(properties::remove);
+ this.properties.add(new WrapperPlayServerUpdateAttributes.Property(attribute, value, modifiers));
+ refresh();
+ }
+
+ public void setAttribute(Attribute attribute, double value, WrapperPlayServerUpdateAttributes.PropertyModifier modifier) {
+ setAttribute(attribute, value, Collections.singletonList(modifier));
+ }
+
+ public void setAttribute(Attribute attribute, double value) {
+ setAttribute(attribute, value, Collections.emptyList());
+ }
+
+ public List getProperties() {
+ return new ArrayList<>(properties);
+ }
+
+ public void forEach(Consumer action) {
+ properties.forEach(action);
+ }
+
+ public void clear() {
+ properties.clear();
+ refresh();
+ }
+
+ public void removeAttribute(Attribute attribute, WrapperPlayServerUpdateAttributes.PropertyModifier modifier) {
+ this.properties.stream()
+ .filter(property -> property.getAttribute() == attribute)
+ .findFirst().ifPresent(property -> {
+ property.getModifiers().remove(modifier);
+ if (property.getModifiers().isEmpty()) {
+ properties.remove(property);
+ }
+ });
+ refresh();
+ }
+
+ public void removeAttribute(Attribute attribute) {
+ this.properties.stream()
+ .filter(property -> property.getAttribute() == attribute)
+ .findFirst().ifPresent(properties::remove);
+ refresh();
+ }
+
+
+ public void refresh() {
+ entity.sendPacketToViewers(createPacket());
+ }
+
+ public WrapperPlayServerUpdateAttributes createPacket() {
+ return new WrapperPlayServerUpdateAttributes(entity.getEntityId(), properties);
+ }
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperLivingEntity.java b/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperLivingEntity.java
index 85e3ff5..91e6090 100644
--- a/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperLivingEntity.java
+++ b/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperLivingEntity.java
@@ -1,5 +1,6 @@
package me.tofaa.entitylib.wrapper;
+import com.github.retrooper.packetevents.protocol.attribute.Attribute;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.player.HumanoidArm;
@@ -7,20 +8,23 @@
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
import org.jetbrains.annotations.Nullable;
+import java.util.List;
import java.util.UUID;
public class WrapperLivingEntity extends WrapperEntity{
private final WrapperEntityEquipment equipment;
-
+ private final WrapperEntityAttributes attributes;
public WrapperLivingEntity(int entityId, UUID uuid, EntityType entityType, EntityMeta entityMeta) {
super(entityId, uuid, entityType, entityMeta);
this.equipment = new WrapperEntityEquipment(this);
+ this.attributes = new WrapperEntityAttributes(this);
}
@Override
@@ -29,6 +33,12 @@ public void refresh() {
equipment.refresh();
}
+ public WrapperEntityAttributes getAttributes() {
+ return attributes;
+ }
+
+
+
/**
* Adds a potion effect to the entity.
* EntityLib will not keep track of the potions you give or what you do with them,
diff --git a/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java b/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java
index 1c32de9..4cdfca4 100644
--- a/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java
+++ b/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java
@@ -79,4 +79,5 @@ public EventHandler getEventHandler() {
public P getHandle() {
return handle;
}
+
}
diff --git a/model-engine-addon/build.gradle b/model-engine-addon/build.gradle
new file mode 100644
index 0000000..4488d2f
--- /dev/null
+++ b/model-engine-addon/build.gradle
@@ -0,0 +1,8 @@
+repositories {
+ maven { url 'https://mvn.lumine.io/repository/maven-public/' }
+}
+
+dependencies {
+// compileOnly 'com.ticxo.modelengine:ModelEngine:R4.0.4'
+ api(project(":api"))
+}
diff --git a/model-engine-addon/src/main/java/me/tofaa/entitylib/modelengine/ELibBaseEntity.java b/model-engine-addon/src/main/java/me/tofaa/entitylib/modelengine/ELibBaseEntity.java
new file mode 100644
index 0000000..84bebab
--- /dev/null
+++ b/model-engine-addon/src/main/java/me/tofaa/entitylib/modelengine/ELibBaseEntity.java
@@ -0,0 +1,5 @@
+package me.tofaa.entitylib.modelengine;
+
+public class ELibBaseEntity {
+
+}
diff --git a/settings.gradle b/settings.gradle
index 522ac72..93c431b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -11,6 +11,7 @@ include 'common'
if (!Boolean.parseBoolean(System.getenv("JITPACK"))) {
include 'code-gen'
include 'test-plugin'
+ include 'model-engine-addon'
}
include 'platforms:velocity'
findProject(':platforms:velocity')?.name = 'velocity'
diff --git a/test-plugin/build.gradle b/test-plugin/build.gradle
index 46fec5a..f568298 100644
--- a/test-plugin/build.gradle
+++ b/test-plugin/build.gradle
@@ -32,15 +32,14 @@ repositories {
dependencies {
compileOnly('org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT')
- compileOnly('com.github.retrooper.packetevents:spigot:2.0.2')
+ compileOnly('com.github.retrooper.packetevents:spigot:2.3.0')
implementation(project(":platforms:spigot"))
}
-tasks {
- runServer {
- minecraftVersion("1.20.4")
- downloadPlugins {
- modrinth("packetevents", "2.2.1")
- }
+
+runServer {
+ minecraftVersion("1.20.4")
+ downloadPlugins {
+ modrinth("packetevents", "6Rjr7zyF")
}
}
\ No newline at end of file
diff --git a/test-plugin/src/main/java/me/tofaa/testentitylib/TestEntityLibPlugin.java b/test-plugin/src/main/java/me/tofaa/testentitylib/TestEntityLibPlugin.java
index 3f4a3da..c8baf17 100644
--- a/test-plugin/src/main/java/me/tofaa/testentitylib/TestEntityLibPlugin.java
+++ b/test-plugin/src/main/java/me/tofaa/testentitylib/TestEntityLibPlugin.java
@@ -24,8 +24,6 @@
public class TestEntityLibPlugin extends JavaPlugin {
- private SpigotEntityLibAPI api;
-
@Override
public void onEnable() {
@@ -34,10 +32,10 @@ public void onEnable() {
.debugMode()
.tickTickables()
.trackPlatformEntities()
+ .useBstats()
.usePlatformLogger();
EntityLib.init(platform, settings);
- api = platform.getAPI();
CommandMap commandMap;
try {
diff --git a/test-plugin/src/main/java/me/tofaa/testentitylib/TestMassivePigCommand.java b/test-plugin/src/main/java/me/tofaa/testentitylib/TestMassivePigCommand.java
new file mode 100644
index 0000000..1797574
--- /dev/null
+++ b/test-plugin/src/main/java/me/tofaa/testentitylib/TestMassivePigCommand.java
@@ -0,0 +1,46 @@
+package me.tofaa.testentitylib;
+
+import com.github.retrooper.packetevents.protocol.attribute.Attributes;
+import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
+import me.tofaa.entitylib.EntityLib;
+import me.tofaa.entitylib.wrapper.WrapperLivingEntity;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.defaults.BukkitCommand;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+
+public class TestMassivePigCommand extends BukkitCommand {
+
+ private WrapperLivingEntity pig;
+
+ public TestMassivePigCommand() {
+ super("testmassivepig");
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] strings) {
+ if (!(commandSender instanceof Player)) return false;
+ Player player = (Player) commandSender;
+ if (pig != null) {
+ pig.remove();
+ pig = null;
+ player.sendMessage("Large pig removed");
+ return true;
+ }
+ pig = EntityLib.getApi().createEntity(EntityTypes.PIG);
+ pig.getAttributes().setAttribute(
+ Attributes.GENERIC_SCALE,
+ 10,
+ new WrapperPlayServerUpdateAttributes.PropertyModifier(
+ UUID.randomUUID(),
+ 10,
+ WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.MULTIPLY_BASE
+ )
+ );
+ player.sendMessage("Large pig spawned");
+ return true;
+ }
+}