diff --git a/gradle.properties b/gradle.properties index 0ecca93..f4dc97a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.jvmargs=-Xmx1G # check these on https://fabricmc.net/versions.html minecraft_version=1.18.2 yarn_mappings=1.18.2+build.3 - loader_version=0.13.3 + loader_version=0.14.5 # Mod Properties mod_version = 1.1.0 diff --git a/src/main/java/errorcraft/entitymodifiers/entity/modifier/Deserialisers.java b/src/main/java/errorcraft/entitymodifiers/entity/modifier/Deserialisers.java index f5af8c3..fd6a697 100644 --- a/src/main/java/errorcraft/entitymodifiers/entity/modifier/Deserialisers.java +++ b/src/main/java/errorcraft/entitymodifiers/entity/modifier/Deserialisers.java @@ -1,6 +1,9 @@ package errorcraft.entitymodifiers.entity.modifier; import com.google.gson.GsonBuilder; +import errorcraft.entitymodifiers.util.RelativeNumberProvider; +import errorcraft.entitymodifiers.world.position.provider.PositionProvider; +import errorcraft.entitymodifiers.world.position.provider.PositionProviderTypes; import net.minecraft.loot.context.LootContext; import net.minecraft.loot.provider.number.LootNumberProvider; import net.minecraft.loot.provider.number.LootNumberProviderTypes; @@ -12,9 +15,11 @@ private Deserialisers() {} public static GsonBuilder createEntityModifierSerialiser() { return new GsonBuilder() - .registerTypeHierarchyAdapter(EntityModifier.class, EntityModifierTypes.createGsonAdapter()) - .registerTypeHierarchyAdapter(LootNumberProvider.class, LootNumberProviderTypes.createGsonSerializer()) - .registerTypeHierarchyAdapter(LootScoreProvider.class, LootScoreProviderTypes.createGsonSerializer()) - .registerTypeHierarchyAdapter(LootContext.EntityTarget.class, new LootContext.EntityTarget.Serializer()); + .registerTypeHierarchyAdapter(EntityModifier.class, EntityModifierTypes.createGsonAdapter()) + .registerTypeHierarchyAdapter(LootNumberProvider.class, LootNumberProviderTypes.createGsonSerializer()) + .registerTypeHierarchyAdapter(LootScoreProvider.class, LootScoreProviderTypes.createGsonSerializer()) + .registerTypeHierarchyAdapter(LootContext.EntityTarget.class, new LootContext.EntityTarget.Serializer()) + .registerTypeHierarchyAdapter(PositionProvider.class, PositionProviderTypes.createGsonAdapter()) + .registerTypeHierarchyAdapter(RelativeNumberProvider.class, new RelativeNumberProvider.Serialiser()); } } diff --git a/src/main/java/errorcraft/entitymodifiers/entity/modifier/EntityModifierTypes.java b/src/main/java/errorcraft/entitymodifiers/entity/modifier/EntityModifierTypes.java index f2a276c..1808584 100644 --- a/src/main/java/errorcraft/entitymodifiers/entity/modifier/EntityModifierTypes.java +++ b/src/main/java/errorcraft/entitymodifiers/entity/modifier/EntityModifierTypes.java @@ -19,6 +19,7 @@ public class EntityModifierTypes { public static final EntityModifierType SET_CUSTOM_NAME = register("set_custom_name", new SetCustomNameEntityModifier.Serialiser()); public static final EntityModifierType SET_ABSORPTION = register("set_absorption", new SetAbsorptionEntityModifier.Serialiser()); public static final EntityModifierType SET_SATURATION = register("set_saturation", new SetSaturationEntityModifier.Serialiser()); + public static final EntityModifierType SET_POSITION = register("set_position", new SetPositionEntityModifier.Serialiser()); public static Object createGsonAdapter() { return JsonSerializing.createSerializerBuilder(ENTITY_MODIFIER_TYPE, "function", "function", EntityModifier::getType).build(); diff --git a/src/main/java/errorcraft/entitymodifiers/entity/modifier/modifiers/SetPositionEntityModifier.java b/src/main/java/errorcraft/entitymodifiers/entity/modifier/modifiers/SetPositionEntityModifier.java new file mode 100644 index 0000000..20d0a64 --- /dev/null +++ b/src/main/java/errorcraft/entitymodifiers/entity/modifier/modifiers/SetPositionEntityModifier.java @@ -0,0 +1,58 @@ +package errorcraft.entitymodifiers.entity.modifier.modifiers; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import errorcraft.entitymodifiers.entity.modifier.EntityModifier; +import errorcraft.entitymodifiers.entity.modifier.EntityModifierType; +import errorcraft.entitymodifiers.entity.modifier.EntityModifierTypes; +import errorcraft.entitymodifiers.world.position.provider.PositionProvider; +import net.minecraft.entity.Entity; +import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.provider.number.LootNumberProvider; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.JsonHelper; +import net.minecraft.util.math.Vec3d; + +public class SetPositionEntityModifier implements EntityModifier { + private final PositionProvider position; + + public SetPositionEntityModifier(PositionProvider position) { + this.position = position; + } + + @Override + public EntityModifierType getType() { + return EntityModifierTypes.SET_POSITION; + } + + @Override + public Entity apply(Entity entity, LootContext lootContext) { + Vec3d newPos = this.position.getPosition(entity.getPos(), entity.getRotationClient(), lootContext); + entity.setPosition(newPos); + if (entity instanceof ServerPlayerEntity player) { + setPlayerPosition(player, newPos); + } + return entity; + } + + private static void setPlayerPosition(ServerPlayerEntity player, Vec3d pos) { + if (player.isSleeping()) { + player.wakeUp(true, true); + } + player.requestTeleportAndDismount(pos.getX(), pos.getY(), pos.getZ()); + } + + public static class Serialiser implements EntityModifier.Serialiser { + @Override + public void toJson(JsonObject json, SetPositionEntityModifier object, JsonSerializationContext context) { + json.add("position", context.serialize(object.position)); + } + + @Override + public SetPositionEntityModifier fromJson(JsonObject json, JsonDeserializationContext context) { + PositionProvider position = JsonHelper.deserialize(json, "position", context, PositionProvider.class); + return new SetPositionEntityModifier(position); + } + } +} diff --git a/src/main/java/errorcraft/entitymodifiers/util/RelativeNumberProvider.java b/src/main/java/errorcraft/entitymodifiers/util/RelativeNumberProvider.java new file mode 100644 index 0000000..c01513c --- /dev/null +++ b/src/main/java/errorcraft/entitymodifiers/util/RelativeNumberProvider.java @@ -0,0 +1,62 @@ +package errorcraft.entitymodifiers.util; + +import com.google.gson.*; +import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.provider.number.ConstantLootNumberProvider; +import net.minecraft.loot.provider.number.LootNumberProvider; +import net.minecraft.util.JsonHelper; + +import java.lang.reflect.Type; + +public class RelativeNumberProvider { + private final LootNumberProvider value; + private final boolean relative; + + public RelativeNumberProvider(LootNumberProvider value, boolean relative) { + this.value = value; + this.relative = relative; + } + + public double getDouble(double currentValue, LootContext context) { + if (this.relative) { + return currentValue + this.value.nextFloat(context); + } + return this.value.nextFloat(context); + } + + public float getFloat(float currentValue, LootContext context) { + if (this.relative) { + return currentValue + this.value.nextFloat(context); + } + return this.value.nextFloat(context); + } + + public int getInt(int currentValue, LootContext context) { + if (this.relative) { + return currentValue + this.value.nextInt(context); + } + return this.value.nextInt(context); + } + + public static class Serialiser implements JsonDeserializer, JsonSerializer { + @Override + public RelativeNumberProvider deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonPrimitive()) { + return new RelativeNumberProvider(ConstantLootNumberProvider.create(json.getAsFloat()), false); + } + + JsonObject jsonObject = JsonHelper.asObject(json, "value"); + LootNumberProvider value = JsonHelper.deserialize(jsonObject, "value", context, LootNumberProvider.class); + boolean relative = JsonHelper.getBoolean(jsonObject, "relative", false); + return new RelativeNumberProvider(value, relative); + } + + @Override + public JsonElement serialize(RelativeNumberProvider object, Type type, JsonSerializationContext context) { + JsonObject json = new JsonObject(); + json.add("value", context.serialize(object.value)); + json.addProperty("relative", object.relative); + return json; + } + } +} diff --git a/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProvider.java b/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProvider.java new file mode 100644 index 0000000..7387355 --- /dev/null +++ b/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProvider.java @@ -0,0 +1,13 @@ +package errorcraft.entitymodifiers.world.position.provider; + +import net.minecraft.loot.context.LootContext; +import net.minecraft.util.JsonSerializer; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; + +public interface PositionProvider { + PositionProviderType getType(); + Vec3d getPosition(Vec3d currentPosition, Vec2f rotation, LootContext lootContext); + + interface Serialiser extends JsonSerializer {} +} diff --git a/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProviderType.java b/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProviderType.java new file mode 100644 index 0000000..2c40dac --- /dev/null +++ b/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProviderType.java @@ -0,0 +1,10 @@ +package errorcraft.entitymodifiers.world.position.provider; + +import net.minecraft.util.JsonSerializableType; +import net.minecraft.util.JsonSerializer; + +public class PositionProviderType extends JsonSerializableType { + public PositionProviderType(JsonSerializer jsonSerializer) { + super(jsonSerializer); + } +} diff --git a/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProviderTypes.java b/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProviderTypes.java new file mode 100644 index 0000000..7f14f16 --- /dev/null +++ b/src/main/java/errorcraft/entitymodifiers/world/position/provider/PositionProviderTypes.java @@ -0,0 +1,25 @@ +package errorcraft.entitymodifiers.world.position.provider; + +import errorcraft.entitymodifiers.mixin.registry.RegistryAccessor; +import errorcraft.entitymodifiers.world.position.provider.providers.LocalPositionProvider; +import errorcraft.entitymodifiers.world.position.provider.providers.WorldPositionProvider; +import net.minecraft.util.Identifier; +import net.minecraft.util.JsonSerializing; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; + +public class PositionProviderTypes { + public static final RegistryKey> POSITION_PROVIDER_TYPE_KEY = RegistryAccessor.createRegistryKey("position_provider_type"); + public static final Registry POSITION_PROVIDER_TYPE = RegistryAccessor.create(POSITION_PROVIDER_TYPE_KEY, registry -> PositionProviderTypes.WORLD); + + public static final PositionProviderType WORLD = register("world", new WorldPositionProvider.Serialiser()); + public static final PositionProviderType LOCAL = register("local", new LocalPositionProvider.Serialiser()); + + public static Object createGsonAdapter() { + return JsonSerializing.createSerializerBuilder(POSITION_PROVIDER_TYPE, "type", "type", PositionProvider::getType).build(); + } + + private static PositionProviderType register(String id, PositionProvider.Serialiser serialiser) { + return Registry.register(POSITION_PROVIDER_TYPE, new Identifier(id), new PositionProviderType(serialiser)); + } +} diff --git a/src/main/java/errorcraft/entitymodifiers/world/position/provider/providers/LocalPositionProvider.java b/src/main/java/errorcraft/entitymodifiers/world/position/provider/providers/LocalPositionProvider.java new file mode 100644 index 0000000..ba72245 --- /dev/null +++ b/src/main/java/errorcraft/entitymodifiers/world/position/provider/providers/LocalPositionProvider.java @@ -0,0 +1,59 @@ +package errorcraft.entitymodifiers.world.position.provider.providers; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import errorcraft.entitymodifiers.world.position.provider.PositionProvider; +import errorcraft.entitymodifiers.world.position.provider.PositionProviderType; +import errorcraft.entitymodifiers.world.position.provider.PositionProviderTypes; +import net.minecraft.command.argument.LookingPosArgument; +import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.provider.number.LootNumberProvider; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.util.JsonHelper; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; + +public class LocalPositionProvider implements PositionProvider { + private final LootNumberProvider left; + private final LootNumberProvider up; + private final LootNumberProvider forwards; + + public LocalPositionProvider(LootNumberProvider left, LootNumberProvider up, LootNumberProvider forwards) { + this.left = left; + this.up = up; + this.forwards = forwards; + } + + @Override + public PositionProviderType getType() { + return PositionProviderTypes.LOCAL; + } + + @Override + public Vec3d getPosition(Vec3d currentPosition, Vec2f rotation, LootContext lootContext) { + double leftOffset = this.left.nextFloat(lootContext); + double upOffset = this.up.nextFloat(lootContext); + double forwardsOffset = this.forwards.nextFloat(lootContext); + LookingPosArgument argument = new LookingPosArgument(leftOffset, upOffset, forwardsOffset); + ServerCommandSource commandSource = new ServerCommandSource(null, currentPosition, rotation, null, 0, null, null, null, null); + return argument.toAbsolutePos(commandSource); + } + + public static class Serialiser implements PositionProvider.Serialiser { + @Override + public void toJson(JsonObject json, LocalPositionProvider object, JsonSerializationContext context) { + json.add("left", context.serialize(object.left)); + json.add("up", context.serialize(object.up)); + json.add("forwards", context.serialize(object.forwards)); + } + + @Override + public LocalPositionProvider fromJson(JsonObject json, JsonDeserializationContext context) { + LootNumberProvider left = JsonHelper.deserialize(json, "left", context, LootNumberProvider.class); + LootNumberProvider up = JsonHelper.deserialize(json, "up", context, LootNumberProvider.class); + LootNumberProvider forwards = JsonHelper.deserialize(json, "forwards", context, LootNumberProvider.class); + return new LocalPositionProvider(left, up, forwards); + } + } +} diff --git a/src/main/java/errorcraft/entitymodifiers/world/position/provider/providers/WorldPositionProvider.java b/src/main/java/errorcraft/entitymodifiers/world/position/provider/providers/WorldPositionProvider.java new file mode 100644 index 0000000..55386ff --- /dev/null +++ b/src/main/java/errorcraft/entitymodifiers/world/position/provider/providers/WorldPositionProvider.java @@ -0,0 +1,54 @@ +package errorcraft.entitymodifiers.world.position.provider.providers; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import errorcraft.entitymodifiers.util.RelativeNumberProvider; +import errorcraft.entitymodifiers.world.position.provider.PositionProvider; +import errorcraft.entitymodifiers.world.position.provider.PositionProviderType; +import errorcraft.entitymodifiers.world.position.provider.PositionProviderTypes; +import net.minecraft.loot.context.LootContext; +import net.minecraft.util.JsonHelper; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; + +public class WorldPositionProvider implements PositionProvider { + private final RelativeNumberProvider x; + private final RelativeNumberProvider y; + private final RelativeNumberProvider z; + + public WorldPositionProvider(RelativeNumberProvider x, RelativeNumberProvider y, RelativeNumberProvider z) { + this.x = x; + this.y = y; + this.z = z; + } + + public PositionProviderType getType() { + return PositionProviderTypes.WORLD; + } + + @Override + public Vec3d getPosition(Vec3d currentPosition, Vec2f rotation, LootContext lootContext) { + double newX = this.x.getDouble(currentPosition.getX(), lootContext); + double newY = this.y.getDouble(currentPosition.getY(), lootContext); + double newZ = this.z.getDouble(currentPosition.getZ(), lootContext); + return new Vec3d(newX, newY, newZ); + } + + public static class Serialiser implements PositionProvider.Serialiser { + @Override + public void toJson(JsonObject json, WorldPositionProvider object, JsonSerializationContext context) { + json.add("x", context.serialize(object.x)); + json.add("y", context.serialize(object.y)); + json.add("z", context.serialize(object.z)); + } + + @Override + public WorldPositionProvider fromJson(JsonObject json, JsonDeserializationContext context) { + RelativeNumberProvider x = JsonHelper.deserialize(json, "x", context, RelativeNumberProvider.class); + RelativeNumberProvider y = JsonHelper.deserialize(json, "y", context, RelativeNumberProvider.class); + RelativeNumberProvider z = JsonHelper.deserialize(json, "z", context, RelativeNumberProvider.class); + return new WorldPositionProvider(x, y, z); + } + } +}