diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 5c411f08..a0da2265 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -64,7 +64,7 @@ public class CarpetServer // static for now - easier to handle all around the co { TickSpeed.tick(server); HUDController.update_hud(server); - scriptServer.events.tick(); + scriptServer.tick(); //in case something happens CarpetSettings.impendingFillSkipUpdates = false; diff --git a/src/main/java/carpet/commands/ScriptCommand.java b/src/main/java/carpet/commands/ScriptCommand.java index dbd31102..dd9034bf 100644 --- a/src/main/java/carpet/commands/ScriptCommand.java +++ b/src/main/java/carpet/commands/ScriptCommand.java @@ -206,7 +206,7 @@ public class ScriptCommand suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.listAvailableModules(),bb)). executes((cc) -> { - boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "package")); + boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "package"), false); return success?1:0; }) ); diff --git a/src/main/java/carpet/helpers/Tracer.java b/src/main/java/carpet/helpers/Tracer.java new file mode 100644 index 00000000..c49cfc19 --- /dev/null +++ b/src/main/java/carpet/helpers/Tracer.java @@ -0,0 +1,16 @@ +package carpet.helpers; + +import net.minecraft.entity.Entity; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.RayTraceContext; + +public class Tracer +{ + public static HitResult traceEntityLook(Entity entity, double reach) { + Vec3d vec3d_1 = entity.getCameraPosVec(1.0F); + Vec3d vec3d_2 = entity.getRotationVec(1.0F); + Vec3d vec3d_3 = vec3d_1.add(vec3d_2.x * reach, vec3d_2.y * reach, vec3d_2.z * reach); + return entity.world.rayTrace(new RayTraceContext(vec3d_1, vec3d_3, RayTraceContext.ShapeType.OUTLINE, RayTraceContext.FluidHandling.ANY, entity)); + } +} diff --git a/src/main/java/carpet/mixins/Entity_horseFixMixin.java b/src/main/java/carpet/mixins/Entity_horseFixMixin.java new file mode 100644 index 00000000..685c21a4 --- /dev/null +++ b/src/main/java/carpet/mixins/Entity_horseFixMixin.java @@ -0,0 +1,35 @@ +package carpet.mixins; + +import carpet.settings.CarpetSettings; +import net.minecraft.client.network.packet.EntityPositionS2CPacket; +import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Entity.class) +public abstract class Entity_horseFixMixin +{ + @Shadow private Entity vehicle; + + @Shadow public abstract World getEntityWorld(); + + @Inject(method = "stopRiding", at = @At("HEAD")) + private void resetNavigation(CallbackInfo ci) + { + if (vehicle != null && vehicle instanceof MobEntity && CarpetSettings.horseWanderingFix) + { + ((MobEntity) vehicle).getNavigation().stop(); + if (!getEntityWorld().isClient) + { + ((ServerWorld) getEntityWorld()).method_14178().sendToNearbyPlayers((Entity)(Object)this, new EntityPositionS2CPacket(vehicle)); + } + } + } + +} diff --git a/src/main/java/carpet/mixins/RenderTickCounter_tickSpeedMixin.java b/src/main/java/carpet/mixins/RenderTickCounter_tickSpeedMixin.java new file mode 100644 index 00000000..9e4927e0 --- /dev/null +++ b/src/main/java/carpet/mixins/RenderTickCounter_tickSpeedMixin.java @@ -0,0 +1,23 @@ +package carpet.mixins; + +import carpet.helpers.TickSpeed; +import carpet.settings.CarpetSettings; +import net.minecraft.client.render.RenderTickCounter; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(RenderTickCounter.class) +public class RenderTickCounter_tickSpeedMixin { + @Redirect(method = "beginRenderTick", at = @At( + value = "FIELD", + target = "Lnet/minecraft/client/render/RenderTickCounter;timeScale:F" + )) + private float adjustTickSpeed(RenderTickCounter counter) { + if (CarpetSettings.smoothClientAnimations) + { + return Math.max(50.0f, TickSpeed.mspt); + } + return 50f; + } +} \ No newline at end of file diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 29b5ad6f..042c0ebc 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -3,6 +3,7 @@ package carpet.script; import carpet.CarpetServer; import carpet.fakes.MinecraftServerInterface; import carpet.helpers.FeatureGenerator; +import carpet.helpers.Tracer; import carpet.script.Fluff.TriFunction; import carpet.script.exception.CarpetExpressionException; import carpet.script.exception.ExpressionException; @@ -53,6 +54,9 @@ import net.minecraft.state.StateFactory; import net.minecraft.state.property.Property; import net.minecraft.text.LiteralText; import net.minecraft.util.Identifier; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.EulerAngle; @@ -61,6 +65,8 @@ import net.minecraft.util.registry.Registry; import net.minecraft.world.Heightmap; import net.minecraft.world.LightType; import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; import net.minecraft.world.loot.context.LootContext; import net.minecraft.world.loot.context.LootContextParameters; import org.apache.commons.lang3.tuple.Pair; @@ -275,6 +281,20 @@ public class CarpetExpression return pcount; } + private void forceChunkUpdate(BlockPos pos, ServerWorld world) + { + Chunk chunk = world.getChunk(pos); + chunk.setShouldSave(true); + for (int i = 0; i<16; i++) + { + BlockPos section = new BlockPos((pos.getX()>>4 <<4)+8, 16*i, (pos.getZ()>>4 <<4)+8); + world.method_14178().markForUpdate(section); + world.method_14178().markForUpdate(section.east()); + world.method_14178().markForUpdate(section.west()); + world.method_14178().markForUpdate(section.north()); + } + } + /** *

Blocks / World API

*
@@ -332,6 +352,8 @@ public class CarpetExpression * place_item('piston,x,y,z,'down') // places a piston facing down * place_item('carrot',x,y,z) // attempts to plant a carrot plant. Returns true if could place carrots at that position. * + *

set_biome(pos, biome_name)

+ *

changes biome at that block position.

*

update(pos)

*

Causes a block update at position.

*

block_tick(pos)

@@ -650,7 +672,7 @@ public class CarpetExpression this.expr.addLazyFunction("blast_resistance", -1, (c, t, lv) -> genericStateTest(c, "blast_resistance", lv, (s, p, w) -> new NumericValue(s.getBlock().getBlastResistance()))); - + // Deprecated this.expr.addLazyFunction("top", -1, (c, t, lv) -> { String type = lv.get(0).evalValue(c).getString().toLowerCase(Locale.ROOT); @@ -922,6 +944,41 @@ public class CarpetExpression return (_c, _t) -> retval; }); + /*this.expr.addLazyFunction("trace_block", -1, (c, t, lv) -> { + Value entityValue = lv.get(0).evalValue(c); + if (!(entityValue instanceof EntityValue)) + throw new InternalExpressionException("First argument of trace_block should be an entity"); + Entity e = ((EntityValue) entityValue).getEntity(); + HitResult hitres = Tracer.traceEntityLook(e, 20); + switch (hitres.getType()) + { + case MISS: + return (_c, _t) -> Value.NULL; + case BLOCK: + return (_c, _t) -> new BlockValue(null, e.getEntityWorld(), ((BlockHitResult)hitres).getBlockPos() ); + case ENTITY: + return (_c, _t) -> new EntityValue(((EntityHitResult)hitres).getEntity()); + } + return LazyValue.NULL; + });*/ + + this.expr.addLazyFunction("set_biome", -1, (c, t, lv) -> { + CarpetContext cc = (CarpetContext)c; + BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + if (lv.size() == locator.offset) + throw new InternalExpressionException("set_biome needs a biome name as an argument"); + String biomeName = lv.get(locator.offset+0).evalValue(c).getString(); + Biome biome = Registry.BIOME.get(new Identifier(biomeName)); + if (biome == null) + throw new InternalExpressionException("Unknown biome: "+biomeName); + ServerWorld world = cc.s.getWorld(); + BlockPos pos = locator.block.getPos(); + Chunk chunk = world.getChunk(pos); + chunk.getBiomeArray()[(pos.getX() & 15) | (pos.getZ() & 15) << 4] = biome; + this.forceChunkUpdate(pos, world); + return LazyValue.NULL; + }); + // need get_biome } @@ -2454,9 +2511,14 @@ public class CarpetExpression this.expr.addLazyFunction("plop", 4, (c, t, lv) ->{ BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext)c, lv, 0); - Boolean res = FeatureGenerator.spawn(lv.get(locator.offset).evalValue(c).getString(), ((CarpetContext)c).s.getWorld(), locator.block.getPos()); + if (lv.size() <= locator.offset) + throw new InternalExpressionException("plop needs extra argument indicating what to plop"); + String what = lv.get(locator.offset).evalValue(c).getString(); + Boolean res = FeatureGenerator.spawn(what, ((CarpetContext)c).s.getWorld(), locator.block.getPos()); if (res == null) return (c_, t_) -> Value.NULL; + if (what.equalsIgnoreCase("boulder")) // there might be more of those + this.forceChunkUpdate(locator.block.getPos(), ((CarpetContext)c).s.getWorld()); return (c_, t_) -> new NumericValue(res); }); diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 0b686ad3..b736b15a 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -1,7 +1,6 @@ package carpet.script; import carpet.CarpetServer; -import carpet.settings.CarpetSettings; import carpet.script.bundled.CameraPathModule; import carpet.script.bundled.FileModule; import carpet.script.bundled.ModuleInterface; @@ -45,7 +44,7 @@ public class CarpetScriptServer public CarpetScriptServer() { - globalHost = createMinecraftScriptHost(null); + globalHost = createMinecraftScriptHost(null, null); events = new CarpetEventServer(); modules = new HashMap<>(); tickStart = 0L; @@ -113,7 +112,7 @@ public class CarpetScriptServer } - private static ScriptHost createMinecraftScriptHost(String name) + private static ScriptHost createMinecraftScriptHost(String name, ModuleInterface code) { ScriptHost host = new ScriptHost(name); host.globalVariables.put("_x", (c, t) -> Value.ZERO); @@ -122,11 +121,12 @@ public class CarpetScriptServer return host; } - public boolean addScriptHost(ServerCommandSource source, String name) + public boolean addScriptHost(ServerCommandSource source, String name, boolean perPlayer) { + //TODO add per player modules to support player actions better on a server name = name.toLowerCase(Locale.ROOT); - ScriptHost newHost = createMinecraftScriptHost(name); ModuleInterface module = getModule(name); + ScriptHost newHost = createMinecraftScriptHost(name, module); if (module == null) { Messenger.m(source, "r Unable to locate the package, but created empty host "+name+" instead"); @@ -330,4 +330,9 @@ public class CarpetScriptServer } return true; } + + public void tick() + { + events.tick(); + } } diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 70a7c762..88ac9cac 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -506,6 +506,14 @@ public class Expression implements Cloneable { throw new ExpressionException(e, token, "Your math is wrong, "+exc.getMessage()); } + catch (ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, token, "Error while evaluating expression: "+exc.getMessage()); + } } }); } @@ -532,6 +540,14 @@ public class Expression implements Cloneable { throw new ExpressionException(e, t, "Your math is wrong, "+exc.getMessage()); } + catch (ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage()); + } } }); } @@ -557,6 +573,14 @@ public class Expression implements Cloneable { throw new ExpressionException(e, token, "Your math is wrong, "+exc.getMessage()); } + catch (ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, token, "Error while evaluating expression: "+exc.getMessage()); + } } }); } @@ -663,6 +687,14 @@ public class Expression implements Cloneable { throw new ExpressionException(e, t, "Your math is wrong, "+exc.getMessage()); } + catch (ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage()); + } } }); } @@ -725,7 +757,7 @@ public class Expression implements Cloneable { retVal = returnStatement.retval; } - catch (ThrowStatement throwStatement) + catch (ThrowStatement throwStatement) // might not be really necessary { retVal = throwStatement.retval; rethrow = true; @@ -738,6 +770,14 @@ public class Expression implements Cloneable { throw new ExpressionException(function_context, t, "Your math is wrong, "+exc.getMessage()); } + catch (ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage()); + } for (String global: globals) { LazyValue lv = newFrame.getVariable(global); diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index c8d55378..082ecfdd 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -108,6 +108,18 @@ public abstract class Fluff { throw new ExpressionException(e, t, exc.getMessage()); } + catch (ArithmeticException exc) + { + throw new ExpressionException(e, t, "Your math is wrong, "+exc.getMessage()); + } + catch (Expression.ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage()); + } } } @@ -154,6 +166,14 @@ public abstract class Fluff { throw new ExpressionException(e, t, "Your math is wrong, "+exc.getMessage()); } + catch (Expression.ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage()); + } } } @@ -182,6 +202,14 @@ public abstract class Fluff { throw new ExpressionException(e, t, "Your math is wrong, "+exc.getMessage()); } + catch (Expression.ExitStatement exit) + { + throw exit; + } + catch (Exception exc) + { + throw new ExpressionException(e, t, "Error while evaluating expression: "+exc.getMessage()); + } } @Override diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java index 18852b7a..58651f55 100644 --- a/src/main/java/carpet/script/ScriptHost.java +++ b/src/main/java/carpet/script/ScriptHost.java @@ -1,6 +1,7 @@ package carpet.script; import carpet.CarpetServer; +import carpet.script.bundled.ModuleInterface; import carpet.settings.CarpetSettings; import carpet.script.exception.ExpressionException; import carpet.script.exception.InvalidCallbackException; @@ -30,9 +31,14 @@ public class ScriptHost private String name; public String getName() {return name;} - ScriptHost(String name) + private ModuleInterface myCode; + + ScriptHost(String name) { this(name, null);} + + ScriptHost(String name, ModuleInterface code) { this.name = name; + this.myCode = code; globalVariables.put("euler", (c, t) -> Expression.euler); globalVariables.put("pi", (c, t) -> Expression.PI); globalVariables.put("null", (c, t) -> Value.NULL); @@ -44,6 +50,7 @@ public class ScriptHost globalVariables.put("_i", (c, t) -> Value.ZERO); globalVariables.put("_a", (c, t) -> Value.ZERO); } + public Expression getExpressionForFunction(String name) { return globalFunctions.get(name).getExpression(); diff --git a/src/main/java/carpet/settings/CarpetSettings.java b/src/main/java/carpet/settings/CarpetSettings.java index 02942790..89416edf 100644 --- a/src/main/java/carpet/settings/CarpetSettings.java +++ b/src/main/java/carpet/settings/CarpetSettings.java @@ -223,6 +223,9 @@ public class CarpetSettings @Rule(desc = "fill/clone/setblock and structure blocks cause block updates", category = CREATIVE) public static boolean fillUpdates = true; + @Rule(desc = "smooth client animations with low tps settings", extra = "works only in SP, and will slow down players", category = CREATIVE) + public static boolean smoothClientAnimations; + private static class PushLimitLimits extends Validator { @Override public Integer validate(ServerCommandSource source, ParsedRule currentRule, Integer newValue, String string) { return (newValue>0 && newValue <= 1024) ? newValue : null; @@ -398,4 +401,11 @@ public class CarpetSettings @Rule(desc = "Spawning requires much less CPU and Memory", category = OPTIMIZATION) public static boolean lagFreeSpawning = false; + + @Rule( + desc = "Prevents horses and other mobs to wander into the distance after dismounting", + extra = "Fixes issues with various Joergens wandering off and disappearing client-side", + category = BUGFIX + ) + public static boolean horseWanderingFix = false; } diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index a715a07c..3fb50f52 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -81,6 +81,8 @@ "Entity_portalSuffocationMixin", "PortalForcer_portalSuffocationMixin", + "Entity_horseFixMixin", + "HopperBlockEntityMixin", "ContainerMixin", "ClientConnectionMixin", @@ -113,6 +115,7 @@ "WorldChunk_movableTEMixin" ], "client": [ + "RenderTickCounter_tickSpeedMixin", "MinecraftClientMixin", "IntegratedServerMixin", "InGameHudMixin",