From 32dc6b17e870a263763232201939a3cace2fa785 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 25 Jul 2019 09:08:51 -0300 Subject: [PATCH] entity events --- .../java/carpet/fakes/EntityInterface.java | 9 ++++++ .../mixins/Entity_scarpetEventsMixin.java | 30 +++++++++++++++++++ .../LivingEntity_scarpetEventsMixin.java | 23 ++++++++++++++ .../java/carpet/script/CarpetEventServer.java | 22 ++++++++++++++ .../java/carpet/script/CarpetExpression.java | 15 ++++++++++ src/main/java/carpet/script/Fluff.java | 3 ++ .../java/carpet/script/value/EntityValue.java | 17 +++++++++++ 7 files changed, 119 insertions(+) create mode 100644 src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java create mode 100644 src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java diff --git a/src/main/java/carpet/fakes/EntityInterface.java b/src/main/java/carpet/fakes/EntityInterface.java index deb9a033..6b4a4d0f 100644 --- a/src/main/java/carpet/fakes/EntityInterface.java +++ b/src/main/java/carpet/fakes/EntityInterface.java @@ -1,6 +1,15 @@ package carpet.fakes; +import carpet.script.CarpetContext; +import carpet.script.CarpetEventServer; +import carpet.script.ScriptHost; + public interface EntityInterface { float getMainYaw(float partialTicks); + //scarpet part + void onDeathCallback(String reason); + void setDeathCallback(CarpetContext cc, String function); + void onDamageCallback(); + void setDamageCallback(CarpetEventServer.ScheduledCall call); } diff --git a/src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java b/src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java new file mode 100644 index 00000000..0ee90509 --- /dev/null +++ b/src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java @@ -0,0 +1,30 @@ +package carpet.mixins; + +import carpet.CarpetServer; +import carpet.fakes.EntityInterface; +import carpet.script.CarpetContext; +import carpet.script.CarpetEventServer; +import carpet.script.ScriptHost; +import carpet.settings.CarpetSettings; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Entity.class) +public abstract class Entity_scarpetEventsMixin implements EntityInterface +{ + private CarpetEventServer.ScheduledCall deathCall; + @Override + public void onDeathCallback(String reason) + { + if (deathCall != null) + { + CarpetServer.scriptServer.events.onEntityDeath(deathCall, (Entity)(Object)this, reason); + } + } + + @Override + public void setDeathCallback(CarpetContext cc, String function) + { + deathCall = CarpetServer.scriptServer.events.makeDeathCall(cc, function); + } +} diff --git a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java new file mode 100644 index 00000000..ee51d29e --- /dev/null +++ b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java @@ -0,0 +1,23 @@ +package carpet.mixins; + +import carpet.fakes.EntityInterface; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LivingEntity.class) +public abstract class LivingEntity_scarpetEventsMixin +{ + + @Inject(method = "onDeath", at = @At("HEAD")) + private void onDeathCall(DamageSource damageSource_1, CallbackInfo ci) + { + ((EntityInterface)this).onDeathCallback(damageSource_1.name); + } +} diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 4fcf43d4..e4b0fd0e 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -6,6 +6,7 @@ import carpet.script.value.EntityValue; import carpet.script.value.ListValue; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; +import carpet.settings.CarpetSettings; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.command.ServerCommandSource; @@ -74,6 +75,11 @@ public class CarpetEventServer { CarpetServer.scriptServer.runas(context_origin, context_source, host, udf, args); } + + public void execute(List args) + { + CarpetServer.scriptServer.runas(context_origin, context_source, host, udf, args); + } } public static class CallbackList @@ -347,4 +353,20 @@ public class CarpetEventServer { eventHandlers.get("player_stops_sprinting").call( () -> Arrays.asList(((c, t) -> new EntityValue(player))), player::getCommandSource); } + + public ScheduledCall makeDeathCall(CarpetContext cc, String function) + { + UserDefinedFunction udf = cc.host.globalFunctions.get(function); + if (udf == null || udf.getArguments().size() != 2) + { + // call won't match arguments + return null; + } + return new ScheduledCall(cc, function, null, 0); + } + + public void onEntityDeath(ScheduledCall call, Entity e, String reason) + { + call.execute( Arrays.asList( (c, t)-> new EntityValue(e), (c, t)-> new StringValue(reason))); + } } diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 2fc5dad7..8bb4fb06 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1804,6 +1804,21 @@ public class CarpetExpression ((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size()).stream().map((vv) -> vv.evalValue(c)).collect(Collectors.toList()))); return lv.get(0); }); + + // or update + this.expr.addLazyFunction("entity_event", 3, (c, t, lv) -> + { + Value v = lv.get(0).evalValue(c); + if (!(v instanceof EntityValue)) + throw new InternalExpressionException("First argument to get should be an entity"); + String what = lv.get(1).evalValue(c).getString(); + Value functionValue = lv.get(2).evalValue(c); + String function = null; + if (!(functionValue instanceof NullValue)) + function = functionValue.getString(); + ((EntityValue) v).setEvent((CarpetContext)c, what, function); + return LazyValue.NULL; + }); } /** diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index 5cd29ad4..93b0ca60 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -12,6 +12,9 @@ public abstract class Fluff @FunctionalInterface public interface TriFunction { R apply(A a, B b, C c); } + @FunctionalInterface + public interface TriConsumer { void accept(A a, B b, C c); } + @FunctionalInterface public interface QuadFunction { R apply(A a, B b, C c, D d);} diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 0b5dab95..4c27b140 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -1,8 +1,12 @@ package carpet.script.value; +import carpet.fakes.EntityInterface; import carpet.fakes.MobEntityInterface; import carpet.helpers.Tracer; +import carpet.script.CarpetContext; +import carpet.script.Fluff; import carpet.script.exception.InternalExpressionException; +import carpet.settings.CarpetSettings; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.client.network.packet.EntityPositionS2CPacket; @@ -427,6 +431,7 @@ public class EntityValue extends Value private static void updateVelocity(Entity e) { + e.velocityModified = true; ((ServerWorld)e.getEntityWorld()).method_14178().sendToNearbyPlayers(e, new EntityVelocityUpdateS2CPacket(e)); } @@ -680,6 +685,7 @@ public class EntityValue extends Value } }); //requires mixing + // gamemode // spectate // "fire" @@ -697,4 +703,15 @@ public class EntityValue extends Value // "jump" // "nbt" <-big one, for now use run('data merge entity ... }}; + + public void setEvent(CarpetContext cc, String event, String fun) + { + if (!(events.containsKey(event))) + throw new InternalExpressionException("unknown entity event: " + event); + events.get(event).accept(cc, entity, fun); + } + + private static Map> events = new HashMap>() {{ + put("on_death", (c, e, f) -> { ((EntityInterface)e).setDeathCallback(c, f); }); + }}; }