entity actions

This commit is contained in:
gnembon committed 2020-10-29 11:26:59 -03:00
1 parent 11818e3d57
commit 15ac7a4621
10 files changed
+136 -12

No files matched your search

@@ -50,7 +50,7 @@ public abstract class PlayerEntity_scarpetEventsMixin extends LivingEntity
{ {
if (PLAYER_COLLIDES_WITH_ENTITY.isNeeded() && !world.isClient) if (PLAYER_COLLIDES_WITH_ENTITY.isNeeded() && !world.isClient)
{ {
PLAYER_COLLIDES_WITH_ENTITY.onEntityAction((ServerPlayerEntity)(Object)this, entity, null); PLAYER_COLLIDES_WITH_ENTITY.onEntityHandAction((ServerPlayerEntity)(Object)this, entity, null);
} }
} }
} }
@@ -224,7 +224,7 @@ public class ServerPlayNetworkHandler_scarpetEventsMixin
)) ))
private void onEntityInteract(PlayerInteractEntityC2SPacket playerInteractEntityC2SPacket_1, CallbackInfo ci) private void onEntityInteract(PlayerInteractEntityC2SPacket playerInteractEntityC2SPacket_1, CallbackInfo ci)
{ {
PLAYER_INTERACTS_WITH_ENTITY.onEntityAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), playerInteractEntityC2SPacket_1.getHand()); PLAYER_INTERACTS_WITH_ENTITY.onEntityHandAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), playerInteractEntityC2SPacket_1.getHand());
} }
@Inject(method = "onPlayerInteractEntity", at = @At( @Inject(method = "onPlayerInteractEntity", at = @At(
@@ -234,7 +234,7 @@ public class ServerPlayNetworkHandler_scarpetEventsMixin
private void onEntityAttack(PlayerInteractEntityC2SPacket playerInteractEntityC2SPacket_1, CallbackInfo ci) private void onEntityAttack(PlayerInteractEntityC2SPacket playerInteractEntityC2SPacket_1, CallbackInfo ci)
{ {
//todo add hit and hand in the future //todo add hit and hand in the future
PLAYER_ATTACKS_ENTITY.onEntityAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), null); PLAYER_ATTACKS_ENTITY.onEntityHandAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), null);
} }
@Inject(method = "onButtonClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;updateLastActionTime()V")) @Inject(method = "onButtonClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;updateLastActionTime()V"))
@@ -1,5 +1,8 @@
package carpet.mixins; package carpet.mixins;
import carpet.CarpetSettings;
import carpet.script.CarpetEventServer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LightningEntity; import net.minecraft.entity.LightningEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@@ -12,6 +15,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import static carpet.script.CarpetEventServer.Event.ENTITY_LOAD;
import static carpet.script.CarpetEventServer.Event.LIGHTNING; import static carpet.script.CarpetEventServer.Event.LIGHTNING;
@Mixin(ServerWorld.class) @Mixin(ServerWorld.class)
@@ -30,4 +34,24 @@ public class ServerWorld_scarpetEventMixin
if (LIGHTNING.isNeeded()) LIGHTNING.onWorldEventFlag((ServerWorld) (Object)this, blockPos, bl2?1:0); if (LIGHTNING.isNeeded()) LIGHTNING.onWorldEventFlag((ServerWorld) (Object)this, blockPos, bl2?1:0);
} }
@Inject(method = "loadEntityUnchecked", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/world/ServerChunkManager;loadEntity(Lnet/minecraft/entity/Entity;)V"
))
private void onEntityAddedToWorld(Entity entity, CallbackInfo ci)
{
CarpetEventServer.Event event = ENTITY_LOAD.get(entity.getType());
if (event != null)
{
if (event.isNeeded())
{
event.onEntityAction(entity);
}
}
else
{
CarpetSettings.LOG.error("Failed to handle entity "+entity.getType().getTranslationKey());
}
}
} }
@@ -13,6 +13,7 @@ import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.utils.Messenger; import carpet.utils.Messenger;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
@@ -211,6 +212,11 @@ public class CarpetEventServer
public static class Event public static class Event
{ {
public static final Map<String, Event> byName = new HashMap<>(); public static final Map<String, Event> byName = new HashMap<>();
public static List<String> publicEvents()
{
return byName.entrySet().stream().filter(e -> e.getValue().isPublic).map(Map.Entry::getKey).collect(Collectors.toList());
}
public static final Event TICK = new Event("tick", 0, true) public static final Event TICK = new Event("tick", 0, true)
{ {
@Override @Override
@@ -407,7 +413,7 @@ public class CarpetEventServer
public static final Event PLAYER_INTERACTS_WITH_ENTITY = new Event("player_interacts_with_entity", 3, false) public static final Event PLAYER_INTERACTS_WITH_ENTITY = new Event("player_interacts_with_entity", 3, false)
{ {
@Override @Override
public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) public void onEntityHandAction(ServerPlayerEntity player, Entity entity, Hand enumhand)
{ {
handler.call( () -> Arrays.asList( handler.call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)), ((c, t) -> new EntityValue(player)),
@@ -434,7 +440,7 @@ public class CarpetEventServer
public static final Event PLAYER_ATTACKS_ENTITY = new Event("player_attacks_entity", 2, false) public static final Event PLAYER_ATTACKS_ENTITY = new Event("player_attacks_entity", 2, false)
{ {
@Override @Override
public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) public void onEntityHandAction(ServerPlayerEntity player, Entity entity, Hand enumhand)
{ {
handler.call( () -> Arrays.asList( handler.call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)), ((c, t) -> new EntityValue(player)),
@@ -596,7 +602,7 @@ public class CarpetEventServer
public static final Event PLAYER_COLLIDES_WITH_ENTITY = new Event("player_collides_with_entity", 2, false) public static final Event PLAYER_COLLIDES_WITH_ENTITY = new Event("player_collides_with_entity", 2, false)
{ {
@Override @Override
public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { public void onEntityHandAction(ServerPlayerEntity player, Entity entity, Hand enumhand) {
handler.call( () -> Arrays.asList( handler.call( () -> Arrays.asList(
((c, t) -> new EntityValue(player)), ((c, t) -> new EntityValue(player)),
((c, t) -> new EntityValue(entity)) ((c, t) -> new EntityValue(entity))
@@ -695,17 +701,38 @@ public class CarpetEventServer
} }
}; };
public static final Map<EntityType<?>, Event> ENTITY_LOAD= new HashMap<EntityType<?>, Event>() {{
EntityType.get("zombie");
Registry.ENTITY_TYPE.forEach(et -> {
put(et, new Event("entity_loaded_" + Registry.ENTITY_TYPE.getId(et), 1, true, false)
{
@Override
public void onEntityAction(Entity entity)
{
super.onEntityAction(entity);
}
});
});
}};
// on projectile thrown (arrow from bows, crossbows, tridents, snoballs, e-pearls // on projectile thrown (arrow from bows, crossbows, tridents, snoballs, e-pearls
public final String name; public final String name;
public final CallbackList handler; public final CallbackList handler;
public final boolean globalOnly; public final boolean globalOnly;
public final boolean isPublic; // public events can be targetted with __on_<event> defs
public Event(String name, int reqArgs, boolean isGlobalOnly) public Event(String name, int reqArgs, boolean isGlobalOnly)
{
this(name, reqArgs, isGlobalOnly, true);
}
public Event(String name, int reqArgs, boolean isGlobalOnly, boolean isPublic)
{ {
this.name = name; this.name = name;
this.handler = new CallbackList(reqArgs); this.handler = new CallbackList(reqArgs);
this.globalOnly = isGlobalOnly; this.globalOnly = isGlobalOnly;
this.isPublic = isPublic;
byName.put(name, this); byName.put(name, this);
} }
public boolean isNeeded() public boolean isNeeded()
@@ -724,7 +751,8 @@ public class CarpetEventServer
public void onBlockHit(ServerPlayerEntity player, Hand enumhand, BlockHitResult hitRes) { } public void onBlockHit(ServerPlayerEntity player, Hand enumhand, BlockHitResult hitRes) { }
public void onBlockBroken(ServerPlayerEntity player, BlockPos pos, BlockState previousBS) { } public void onBlockBroken(ServerPlayerEntity player, BlockPos pos, BlockState previousBS) { }
public void onBlockPlaced(ServerPlayerEntity player, BlockPos pos, Hand enumhand, ItemStack itemstack) { } public void onBlockPlaced(ServerPlayerEntity player, BlockPos pos, Hand enumhand, ItemStack itemstack) { }
public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { } public void onEntityHandAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { }
public void onEntityAction(Entity entity) { }
public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, RegistryKey<World> fromDim, RegistryKey<World> dimTo) {} public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, RegistryKey<World> fromDim, RegistryKey<World> dimTo) {}
public void onDamage(Entity target, float amount, DamageSource source) { } public void onDamage(Entity target, float amount, DamageSource source) { }
public void onRecipeSelected(ServerPlayerEntity player, Identifier recipe, boolean fullStack) {} public void onRecipeSelected(ServerPlayerEntity player, Identifier recipe, boolean fullStack) {}
@@ -640,7 +640,7 @@ public class Auxiliary {
throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name");
long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong();
FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, true); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, true, false);
CarpetServer.scriptServer.events.scheduleCall( CarpetServer.scriptServer.events.scheduleCall(
(CarpetContext) c, (CarpetContext) c,
@@ -1,8 +1,10 @@
package carpet.script.api; package carpet.script.api;
import carpet.script.CarpetContext; import carpet.script.CarpetContext;
import carpet.script.CarpetScriptHost;
import carpet.script.Expression; import carpet.script.Expression;
import carpet.script.LazyValue; import carpet.script.LazyValue;
import carpet.script.argument.FunctionArgument;
import carpet.script.argument.Vector3Argument; import carpet.script.argument.Vector3Argument;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import carpet.script.value.EntityValue; import carpet.script.value.EntityValue;
@@ -266,6 +268,16 @@ public class Entities {
return (cc, tt) -> v; return (cc, tt) -> v;
}); });
expression.addLazyFunction("entity_load_handler", -1, (c, t, lv) ->
{
if (lv.size() < 3) throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call");
String entityString = lv.get(0).evalValue(c).getString();
FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, true);
((CarpetScriptHost)c.host).getScriptServer().events.addEventDirectly(entityString, c.host, funArg.function);
};
// or update // or update
expression.addLazyFunction("entity_event", -1, (c, t, lv) -> expression.addLazyFunction("entity_event", -1, (c, t, lv) ->
{ {
@@ -275,6 +287,7 @@ public class Entities {
if (!(v instanceof EntityValue)) if (!(v instanceof EntityValue))
throw new InternalExpressionException("First argument to entity_event should be an entity"); throw new InternalExpressionException("First argument to entity_event should be an entity");
String what = lv.get(1).evalValue(c).getString(); String what = lv.get(1).evalValue(c).getString();
Value functionValue = lv.get(2).evalValue(c); Value functionValue = lv.get(2).evalValue(c);
if (functionValue instanceof NullValue) if (functionValue instanceof NullValue)
functionValue = null; functionValue = null;
@@ -21,7 +21,7 @@ public class FunctionArgument extends Argument
this.function = function; this.function = function;
this.args = args; this.args = args;
} }
public static FunctionArgument findIn(Context c, Module module, List<LazyValue> params, int offset, boolean prematureEvaluation) public static FunctionArgument findIn(Context c, Module module, List<LazyValue> params, int offset, boolean prematureEvaluation, boolean allowNone)
{ {
Value functionValue = params.get(offset).evalValue(c); Value functionValue = params.get(offset).evalValue(c);
if (!(functionValue instanceof FunctionValue)) if (!(functionValue instanceof FunctionValue))
@@ -43,7 +43,7 @@ public class Functions {
//lv.remove(lv.size()-1); // aint gonna cut it // maybe it will because of the eager eval changes //lv.remove(lv.size()-1); // aint gonna cut it // maybe it will because of the eager eval changes
if (t != Context.SIGNATURE) // just call the function if (t != Context.SIGNATURE) // just call the function
{ {
FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, false);
FunctionValue fun = functionArgument.function; FunctionValue fun = functionArgument.function;
Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c); Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c);
return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?)
@@ -17,7 +17,7 @@ public class Threading
{ {
if (lv.size() == 0) if (lv.size() == 0)
throw new InternalExpressionException("'task' requires at least function to call as a parameter"); throw new InternalExpressionException("'task' requires at least function to call as a parameter");
FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, true); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, true, false);
ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.args); ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.args);
Thread.yield(); Thread.yield();
return (cc, tt) -> thread; return (cc, tt) -> thread;
@@ -28,7 +28,7 @@ public class Threading
if (lv.size() < 2) if (lv.size() < 2)
throw new InternalExpressionException("'task' requires at least function to call as a parameter"); throw new InternalExpressionException("'task' requires at least function to call as a parameter");
Value queue = lv.get(0).evalValue(c); Value queue = lv.get(0).evalValue(c);
FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, true); FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, true, false);
ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args);
Thread.yield(); Thread.yield();
return (cc, tt) -> thread; return (cc, tt) -> thread;
@@ -15,6 +15,7 @@ import carpet.script.EntityEventsGroup;
import carpet.script.argument.Vector3Argument; import carpet.script.argument.Vector3Argument;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.mojang.brigadier.StringReader; import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.SpawnGroup;
@@ -70,15 +71,18 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import static carpet.script.value.NBTSerializableValue.nameFromRegistryId; import static carpet.script.value.NBTSerializableValue.nameFromRegistryId;
import static carpet.utils.MobAI.genericJump; import static carpet.utils.MobAI.genericJump;
@@ -210,6 +214,61 @@ public class EntityValue extends Value
"illager", EntityGroup.ILLAGER "illager", EntityGroup.ILLAGER
); );
public static class EntityClassDescriptor
{
public EntityType<?> directType;
public Predicate<? super Entity> filteringPredicate;
public List<EntityType<?>> typeList;
EntityClassDescriptor(EntityType<?> type, Predicate<? super Entity> predicate, Stream<EntityType<?>> types)
{
directType = type;
filteringPredicate = predicate;
typeList = types.collect(Collectors.toList());
}
public Map<String, EntityClassDescriptor> byName = new HashMap<String, EntityClassDescriptor>() {{
Stream<EntityType<?>> allTypes = Registry.ENTITY_TYPE.stream();
Set<EntityType<?>> projectiles = Sets.newHashSet(
EntityType.ARROW, EntityType.DRAGON_FIREBALL
);
Set<EntityType<?>> deads = Sets.newHashSet(
EntityType.AREA_EFFECT_CLOUD, EntityType.BOAT,
)
put("*", new EntityClassDescriptor(null, e -> true, allTypes) );
put("valid", new EntityClassDescriptor(null, EntityPredicates.VALID_ENTITY, allTypes));
put("!valid", new EntityClassDescriptor(null, e -> !e.isAlive(), allTypes));
put("living", Pair.of(null, (e) -> e instanceof LivingEntity && e.isAlive(), allTypes.filter(et -> et.)));
put("!living", Pair.of(null, (e) -> !(e instanceof LivingEntity) && e.isAlive()));
put("projectile", Pair.of(null, (e) -> e instanceof ProjectileEntity && e.isAlive()));
put("!projectile", Pair.of(null, (e) -> !(e instanceof ProjectileEntity) && e.isAlive()));
for (String groupStr : entityGroupMap.keySet())
{
EntityGroup group = entityGroupMap.get(groupStr);
put( groupStr, Pair.of(null, e -> ((e instanceof LivingEntity) && ((LivingEntity) e).getGroup() == group && e.isAlive())));
put("!"+groupStr, Pair.of(null, e -> ((e instanceof LivingEntity) && ((LivingEntity) e).getGroup() != group && e.isAlive())));
}
for (Identifier typeId : Registry.ENTITY_TYPE.getIds())
{
EntityType type = Registry.ENTITY_TYPE.get(typeId);
String mobType = ValueConversions.simplify(typeId);
put( mobType, Pair.of(type, EntityPredicates.VALID_ENTITY));
put("!"+mobType, Pair.of(null, (e) -> e.getType() != type && e.isAlive()));
}
for (SpawnGroup catId : SpawnGroup.values())
{
String catStr = catId.getName();
put( catStr, Pair.of(null, e -> (e.getType().getSpawnGroup() == catId) && e.isAlive()));
put("!"+catStr, Pair.of(null, e -> (e.getType().getSpawnGroup() != catId) && e.isAlive()));
}
}}
}
private static final Map<String, Pair<EntityType<?>, Predicate<? super Entity>>> entityPredicates = private static final Map<String, Pair<EntityType<?>, Predicate<? super Entity>>> entityPredicates =
new HashMap<String, Pair<EntityType<?>, Predicate<? super Entity>>>() new HashMap<String, Pair<EntityType<?>, Predicate<? super Entity>>>()
{{ {{