{
/**
* 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 @@ import org.jetbrains.annotations.ApiStatus;
@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 final class GithubUpdater {
}
@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 final class GithubUpdater {
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 class WrapperEntity implements Tickable, TrackedEntity {
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.protocol.potion.PotionType;
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 class WrapperLivingEntity extends WrapperEntity{
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 abstract class AbstractPlatform