diff --git a/src/main/java/carpet/script/CarpetContext.java b/src/main/java/carpet/script/CarpetContext.java index cfb21eff..0455c1c5 100644 --- a/src/main/java/carpet/script/CarpetContext.java +++ b/src/main/java/carpet/script/CarpetContext.java @@ -18,11 +18,12 @@ public class CarpetContext extends Context public CommandSourceStack s; private final BlockPos origin; - public CarpetContext(CarpetScriptHost host, CommandSourceStack source) { + public CarpetContext(final CarpetScriptHost host, final CommandSourceStack source) + { this(host, source, BlockPos.ZERO); } - public CarpetContext(ScriptHost host, CommandSourceStack source, BlockPos origin) + public CarpetContext(final ScriptHost host, final CommandSourceStack source, final BlockPos origin) { super(host); s = source; @@ -59,7 +60,8 @@ public class CarpetContext extends Context return s.getLevel().registryAccess(); } - public Registry registry(ResourceKey> resourceKey) { + public Registry registry(final ResourceKey> resourceKey) + { return registryAccess().registryOrThrow(resourceKey); } @@ -73,7 +75,7 @@ public class CarpetContext extends Context return origin; } - public void swapSource(CommandSourceStack source) + public void swapSource(final CommandSourceStack source) { s = source; } diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 3c84663d..96a19877 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -22,6 +22,7 @@ import carpet.script.value.ValueConversions; import carpet.utils.CarpetProfiler; import carpet.utils.Messenger; import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -40,6 +41,7 @@ import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; + import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -92,27 +94,31 @@ public class CarpetEventServer public final FunctionValue function; public final List parametrizedArgs; - public Callback(String host, String target, FunctionValue function, List parametrizedArgs) + public Callback(final String host, final String target, final FunctionValue function, final List parametrizedArgs) { this.host = host; this.function = function; this.optionalTarget = target; - this.parametrizedArgs = parametrizedArgs==null?NOARGS:parametrizedArgs; + this.parametrizedArgs = parametrizedArgs == null ? NOARGS : parametrizedArgs; } /** * Used also in entity events - * @param sender - entity command source + * + * @param sender - entity command source * @param runtimeArgs = options */ - public CallbackResult execute(CommandSourceStack sender, List runtimeArgs) + public CallbackResult execute(final CommandSourceStack sender, List runtimeArgs) { if (!this.parametrizedArgs.isEmpty()) { runtimeArgs = new ArrayList<>(runtimeArgs); runtimeArgs.addAll(this.parametrizedArgs); } - if (CarpetServer.scriptServer == null) return CallbackResult.FAIL; // already stopped + if (CarpetServer.scriptServer == null) + { + return CallbackResult.FAIL; // already stopped + } return CarpetServer.scriptServer.events.runEventCall( sender.withPermission(CarpetSettings.runPermissionLevel), host, optionalTarget, function, runtimeArgs); @@ -120,31 +126,33 @@ public class CarpetEventServer /** * Used also in entity events - * @param sender - sender of the signal + * + * @param sender - sender of the signal * @param optionalRecipient - optional target player argument - * @param runtimeArgs = options + * @param runtimeArgs = options */ - public CallbackResult signal(CommandSourceStack sender, ServerPlayer optionalRecipient, List runtimeArgs) + public CallbackResult signal(final CommandSourceStack sender, final ServerPlayer optionalRecipient, final List runtimeArgs) { // recipent of the call doesn't match the handlingHost - if (optionalRecipient != null && !optionalRecipient.getScoreboardName().equals(optionalTarget)) - return CallbackResult.FAIL; - return execute(sender, runtimeArgs); + return optionalRecipient != null && !optionalRecipient.getScoreboardName().equals(optionalTarget) ? CallbackResult.FAIL : execute(sender, runtimeArgs); } @Override public String toString() { - return function.getString()+((host==null)?"":"(from "+host+(optionalTarget == null?"":"/"+optionalTarget)+")"); + return function.getString() + ((host == null) ? "" : "(from " + host + (optionalTarget == null ? "" : "/" + optionalTarget) + ")"); } - public static record Signature(String function, String host, String target) {} - - public static Signature fromString(String str) + + public record Signature(String function, String host, String target) { - Pattern find = Pattern.compile("(\\w+)(?:\\(from (\\w+)(?:/(\\w+))?\\))?"); - Matcher matcher = find.matcher(str); - if(matcher.matches()) + } + + public static Signature fromString(final String str) + { + final Pattern find = Pattern.compile("(\\w+)(?:\\(from (\\w+)(?:/(\\w+))?\\))?"); + final Matcher matcher = find.matcher(str); + if (matcher.matches()) { return new Signature(matcher.group(1), matcher.group(2), matcher.group(3)); } @@ -158,7 +166,7 @@ public class CarpetEventServer private final CarpetContext ctx; public long dueTime; - public ScheduledCall(CarpetContext context, FunctionValue function, List args, long dueTime) + public ScheduledCall(final CarpetContext context, final FunctionValue function, final List args, final long dueTime) { // ignoring target as we will be always calling self super(context.host.getName(), null, function, args); @@ -186,7 +194,7 @@ public class CarpetEventServer final boolean isSystem; final boolean perPlayerDistribution; - public CallbackList(int reqArgs, boolean isSystem, boolean isGlobalOnly) + public CallbackList(final int reqArgs, final boolean isSystem, final boolean isGlobalOnly) { this.callList = new ArrayList<>(); this.removedCalls = new ArrayList<>(); @@ -202,7 +210,7 @@ public class CarpetEventServer return new ArrayList<>(callList); } - private void removeCallsIf(Predicate when) + private void removeCallsIf(final Predicate when) { if (!inCall && !inSignal) { @@ -212,34 +220,38 @@ public class CarpetEventServer // we are ok with list growing in the meantime and parallel access, we are only scanning. for (int i = 0; i < callList.size(); i++) { - Callback call = callList.get(i); - if (when.test(call)) removedCalls.add(call); + final Callback call = callList.get(i); + if (when.test(call)) + { + removedCalls.add(call); + } } } /** * Handles only built-in events from the events system + * * @param argumentSupplier * @param cmdSourceSupplier * @return Whether this event call has been cancelled */ - public boolean call(Supplier> argumentSupplier, Supplier cmdSourceSupplier) + public boolean call(final Supplier> argumentSupplier, final Supplier cmdSourceSupplier) { - if (callList.size() > 0 && CarpetServer.scriptServer != null) + if (!callList.isEmpty() && CarpetServer.scriptServer != null) { - Boolean isCancelled = CarpetServer.scriptServer.events.handleEvents.runIfEnabled( () -> { - CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet events", CarpetProfiler.TYPE.GENERAL); - List argv = argumentSupplier.get(); // empty for onTickDone - CommandSourceStack source; + final Boolean isCancelled = CarpetServer.scriptServer.events.handleEvents.runIfEnabled(() -> { + final CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet events", CarpetProfiler.TYPE.GENERAL); + final List argv = argumentSupplier.get(); // empty for onTickDone + final CommandSourceStack source; try { source = cmdSourceSupplier.get(); } - catch (NullPointerException noReference) // todo figure out what happens when closing. + catch (final NullPointerException noReference) // todo figure out what happens when closing. { return false; } - String nameCheck = perPlayerDistribution ? source.getTextName() : null; + final String nameCheck = perPlayerDistribution ? source.getTextName() : null; assert argv.size() == reqArgs; boolean cancelled = false; try @@ -249,23 +261,33 @@ public class CarpetEventServer inCall = true; for (int i = 0; i < callList.size(); i++) { - Callback call = callList.get(i); + final Callback call = callList.get(i); // supressing calls where target player hosts simply don't match // handling global hosts with player targets is left to when the host is resolved (few calls deeper). - if (nameCheck != null && call.optionalTarget != null && !nameCheck.equals(call.optionalTarget)) continue; - CallbackResult result = call.execute(source, argv); - if(result == CallbackResult.CANCEL) { + if (nameCheck != null && call.optionalTarget != null && !nameCheck.equals(call.optionalTarget)) + { + continue; + } + final CallbackResult result = call.execute(source, argv); + if (result == CallbackResult.CANCEL) + { cancelled = true; break; } - if (result == CallbackResult.FAIL) removedCalls.add(call); + if (result == CallbackResult.FAIL) + { + removedCalls.add(call); + } } } finally { inCall = false; } - for (Callback call : removedCalls) callList.remove(call); + for (final Callback call : removedCalls) + { + callList.remove(call); + } removedCalls.clear(); CarpetProfiler.end_current_section(currentSection); return cancelled; @@ -275,9 +297,12 @@ public class CarpetEventServer return false; } - public int signal(CommandSourceStack sender, ServerPlayer optinoalReceipient, List callArg) + public int signal(final CommandSourceStack sender, final ServerPlayer optinoalReceipient, final List callArg) { - if (callList.isEmpty()) return 0; + if (callList.isEmpty()) + { + return 0; + } int successes = 0; try { @@ -285,7 +310,10 @@ public class CarpetEventServer for (int i = 0; i < callList.size(); i++) { // skipping tracking of fails, its explicit call - if (callList.get(i).signal(sender, optinoalReceipient, callArg) == CallbackResult.SUCCESS) successes++; + if (callList.get(i).signal(sender, optinoalReceipient, callArg) == CallbackResult.SUCCESS) + { + successes++; + } } } finally @@ -295,21 +323,21 @@ public class CarpetEventServer return successes; } - public boolean addFromExternal(CommandSourceStack source, String hostName, String funName, Consumer hostOnEventHandler) + public boolean addFromExternal(final CommandSourceStack source, final String hostName, final String funName, final Consumer hostOnEventHandler) { - ScriptHost host = CarpetServer.scriptServer.getAppHostByName(hostName); + final ScriptHost host = CarpetServer.scriptServer.getAppHostByName(hostName); if (host == null) { // impossible call to add - Messenger.m(source, "r Unknown app "+hostName); + Messenger.m(source, "r Unknown app " + hostName); return false; } hostOnEventHandler.accept(host); - FunctionValue udf = host.getFunction(funName); + final FunctionValue udf = host.getFunction(funName); if (udf == null || udf.getArguments().size() != reqArgs) { // call won't match arguments - Messenger.m(source, "r Callback doesn't expect required number of arguments: "+reqArgs); + Messenger.m(source, "r Callback doesn't expect required number of arguments: " + reqArgs); return false; } String target = null; @@ -319,7 +347,7 @@ public class CarpetEventServer { target = source.getPlayerOrException().getScoreboardName(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { Messenger.m(source, "r Cannot add event to a player scoped app from a command without a player context"); return false; @@ -332,7 +360,8 @@ public class CarpetEventServer callList.add(new Callback(hostName, target, udf, null)); return true; } - public boolean addEventCallInternal(ScriptHost host, FunctionValue function, List args) + + public boolean addEventCallInternal(final ScriptHost host, final FunctionValue function, final List args) { if (function == null || (function.getArguments().size() - args.size()) != reqArgs) { @@ -344,27 +373,27 @@ public class CarpetEventServer return true; } - public void removeEventCall(String hostName, String target, String funName) + public void removeEventCall(final String hostName, final String target, final String funName) { - removeCallsIf((c)-> c.function.getString().equals(funName) + removeCallsIf((c) -> c.function.getString().equals(funName) && (Objects.equals(c.host, hostName)) && (Objects.equals(c.optionalTarget, target)) ); } - public void removeAllCalls(CarpetScriptHost host) + public void removeAllCalls(final CarpetScriptHost host) { - removeCallsIf((c)-> (Objects.equals(c.host, host.getName())) + removeCallsIf((c) -> (Objects.equals(c.host, host.getName())) && (Objects.equals(c.optionalTarget, host.user))); } - public void createChildEvents(CarpetScriptHost host) + public void createChildEvents(final CarpetScriptHost host) { - List copyCalls = new ArrayList<>(); - callList.forEach((c)-> + final List copyCalls = new ArrayList<>(); + callList.forEach((c) -> { if ((Objects.equals(c.host, host.getName())) - && c.optionalTarget == null) + && c.optionalTarget == null) { copyCalls.add(new Callback(c.host, host.user, c.function, c.parametrizedArgs)); } @@ -375,11 +404,15 @@ public class CarpetEventServer public void clearEverything() { // when some moron puts /reload in an event call. - if (inSignal || inCall) callList = new ArrayList<>(); + if (inSignal || inCall) + { + callList = new ArrayList<>(); + } callList.clear(); } - public void sortByPriority(CarpetScriptServer scriptServer) { + public void sortByPriority(final CarpetScriptServer scriptServer) + { callList.sort(Comparator.comparingDouble(c -> -scriptServer.getAppHostByName(c.host).eventPriority)); } } @@ -387,10 +420,14 @@ public class CarpetEventServer public static class Event { public static final Map byName = new HashMap<>(); - public static List publicEvents(CarpetScriptServer server) + + public static List publicEvents(final CarpetScriptServer server) { - List events = byName.values().stream().filter(e -> e.isPublic).collect(Collectors.toList()); - if (server != null) events.addAll(server.events.customEvents.values()); + final List events = byName.values().stream().filter(e -> e.isPublic).collect(Collectors.toList()); + if (server != null) + { + events.addAll(server.events.customEvents.values()); + } return events; } @@ -453,6 +490,7 @@ public class CarpetEventServer { return true; } + @Override public void onTick() { @@ -465,24 +503,22 @@ public class CarpetEventServer public static final Event CHUNK_GENERATED = new Event("chunk_generated", 2, true) { @Override - public void onChunkEvent(ServerLevel world, ChunkPos chPos, boolean generated) + public void onChunkEvent(final ServerLevel world, final ChunkPos chPos, final boolean generated) { - handler.call( () -> - { - return Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4)); - }, () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel(world) + handler.call( + () -> Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4)), + () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel(world) ); } }; public static final Event CHUNK_LOADED = new Event("chunk_loaded", 2, true) { @Override - public void onChunkEvent(ServerLevel world, ChunkPos chPos, boolean generated) + public void onChunkEvent(final ServerLevel world, final ChunkPos chPos, final boolean generated) { - handler.call( () -> - { - return Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4)); - }, () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel(world) + handler.call( + () -> Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4)), + () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel(world) ); } }; @@ -490,7 +526,7 @@ public class CarpetEventServer public static final Event CHUNK_UNLOADED = new Event("chunk_unloaded", 2, true) { @Override - public void onChunkEvent(ServerLevel world, ChunkPos chPos, boolean generated) + public void onChunkEvent(final ServerLevel world, final ChunkPos chPos, final boolean generated) { handler.call( () -> Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4)), @@ -502,45 +538,45 @@ public class CarpetEventServer public static final Event PLAYER_JUMPS = new Event("player_jumps", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_DEPLOYS_ELYTRA = new Event("player_deploys_elytra", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_WAKES_UP = new Event("player_wakes_up", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_ESCAPES_SLEEP = new Event("player_escapes_sleep", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_RIDES = new Event("player_rides", 5, false) { @Override - public void onMountControls(ServerPlayer player, float strafeSpeed, float forwardSpeed, boolean jumping, boolean sneaking) + public void onMountControls(final ServerPlayer player, final float strafeSpeed, final float forwardSpeed, final boolean jumping, final boolean sneaking) { - handler.call( () -> Arrays.asList(new EntityValue(player), + handler.call(() -> Arrays.asList(new EntityValue(player), new NumericValue(forwardSpeed), new NumericValue(strafeSpeed), BooleanValue.of(jumping), BooleanValue.of(sneaking) ), player::createCommandSourceStack); } @@ -548,45 +584,40 @@ public class CarpetEventServer public static final Event PLAYER_USES_ITEM = new Event("player_uses_item", 3, false) { @Override - public boolean onItemAction(ServerPlayer player, InteractionHand enumhand, ItemStack itemstack) + public boolean onItemAction(final ServerPlayer player, final InteractionHand enumhand, final ItemStack itemstack) { - return handler.call( () -> - { - //ItemStack itemstack = player.getStackInHand(enumhand); - return Arrays.asList( - new EntityValue(player), - ValueConversions.of(itemstack, player.getLevel().registryAccess()), - StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand") - ); - }, player::createCommandSourceStack); + return handler.call(() -> + Arrays.asList( + new EntityValue(player), + ValueConversions.of(itemstack, player.getLevel().registryAccess()), + StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand") + ), player::createCommandSourceStack); } }; public static final Event PLAYER_CLICKS_BLOCK = new Event("player_clicks_block", 3, false) { @Override - public boolean onBlockAction(ServerPlayer player, BlockPos blockpos, Direction facing) + public boolean onBlockAction(final ServerPlayer player, final BlockPos blockpos, final Direction facing) { - return handler.call( () -> - { - return Arrays.asList( - new EntityValue(player), - new BlockValue(null, player.getLevel(), blockpos), - StringValue.of(facing.getName()) - ); - }, player::createCommandSourceStack); + return handler.call(() -> + Arrays.asList( + new EntityValue(player), + new BlockValue(null, player.getLevel(), blockpos), + StringValue.of(facing.getName()) + ), player::createCommandSourceStack); } }; public static final Event PLAYER_RIGHT_CLICKS_BLOCK = new Event("player_right_clicks_block", 6, false) { @Override - public boolean onBlockHit(ServerPlayer player, InteractionHand enumhand, BlockHitResult hitRes)//ItemStack itemstack, Hand enumhand, BlockPos blockpos, Direction enumfacing, Vec3d vec3d) + public boolean onBlockHit(final ServerPlayer player, final InteractionHand enumhand, final BlockHitResult hitRes) { - return handler.call( () -> + return handler.call(() -> { - ItemStack itemstack = player.getItemInHand(enumhand); - BlockPos blockpos = hitRes.getBlockPos(); - Direction enumfacing = hitRes.getDirection(); - Vec3 vec3d = hitRes.getLocation().subtract(blockpos.getX(), blockpos.getY(), blockpos.getZ()); + final ItemStack itemstack = player.getItemInHand(enumhand); + final BlockPos blockpos = hitRes.getBlockPos(); + final Direction enumfacing = hitRes.getDirection(); + final Vec3 vec3d = hitRes.getLocation().subtract(blockpos.getX(), blockpos.getY(), blockpos.getZ()); return Arrays.asList( new EntityValue(player), ValueConversions.of(itemstack, player.getLevel().registryAccess()), @@ -605,13 +636,13 @@ public class CarpetEventServer public static final Event PLAYER_INTERACTS_WITH_BLOCK = new Event("player_interacts_with_block", 5, false) { @Override - public boolean onBlockHit(ServerPlayer player, InteractionHand enumhand, BlockHitResult hitRes) + public boolean onBlockHit(final ServerPlayer player, final InteractionHand enumhand, final BlockHitResult hitRes) { - handler.call( () -> + handler.call(() -> { - BlockPos blockpos = hitRes.getBlockPos(); - Direction enumfacing = hitRes.getDirection(); - Vec3 vec3d = hitRes.getLocation().subtract(blockpos.getX(), blockpos.getY(), blockpos.getZ()); + final BlockPos blockpos = hitRes.getBlockPos(); + final Direction enumfacing = hitRes.getDirection(); + final Vec3 vec3d = hitRes.getLocation().subtract(blockpos.getX(), blockpos.getY(), blockpos.getZ()); return Arrays.asList( new EntityValue(player), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand"), @@ -630,9 +661,9 @@ public class CarpetEventServer public static final Event PLAYER_PLACING_BLOCK = new Event("player_placing_block", 4, false) { @Override - public boolean onBlockPlaced(ServerPlayer player, BlockPos pos, InteractionHand enumhand, ItemStack itemstack) + public boolean onBlockPlaced(final ServerPlayer player, final BlockPos pos, final InteractionHand enumhand, final ItemStack itemstack) { - return handler.call( () -> Arrays.asList( + return handler.call(() -> Arrays.asList( new EntityValue(player), ValueConversions.of(itemstack, player.getLevel().registryAccess()), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand"), @@ -643,9 +674,9 @@ public class CarpetEventServer public static final Event PLAYER_PLACES_BLOCK = new Event("player_places_block", 4, false) { @Override - public boolean onBlockPlaced(ServerPlayer player, BlockPos pos, InteractionHand enumhand, ItemStack itemstack) + public boolean onBlockPlaced(final ServerPlayer player, final BlockPos pos, final InteractionHand enumhand, final ItemStack itemstack) { - handler.call( () -> Arrays.asList( + handler.call(() -> Arrays.asList( new EntityValue(player), ValueConversions.of(itemstack, player.getLevel().registryAccess()), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand"), @@ -657,7 +688,7 @@ public class CarpetEventServer public static final Event PLAYER_BREAK_BLOCK = new Event("player_breaks_block", 2, false) { @Override - public boolean onBlockBroken(ServerPlayer player, BlockPos pos, BlockState previousBS) + public boolean onBlockBroken(final ServerPlayer player, final BlockPos pos, final BlockState previousBS) { return handler.call( () -> Arrays.asList(new EntityValue(player), new BlockValue(previousBS, player.getLevel(), pos)), @@ -668,22 +699,22 @@ public class CarpetEventServer public static final Event PLAYER_INTERACTS_WITH_ENTITY = new Event("player_interacts_with_entity", 3, false) { @Override - public boolean onEntityHandAction(ServerPlayer player, Entity entity, InteractionHand enumhand) + public boolean onEntityHandAction(final ServerPlayer player, final Entity entity, final InteractionHand enumhand) { - return handler.call( () -> Arrays.asList( - new EntityValue(player), new EntityValue(entity), StringValue.of(enumhand==InteractionHand.MAIN_HAND?"mainhand":"offhand") + return handler.call(() -> Arrays.asList( + new EntityValue(player), new EntityValue(entity), StringValue.of(enumhand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand") ), player::createCommandSourceStack); } }; public static final Event PLAYER_TRADES = new Event("player_trades", 5, false) { @Override - public void onTrade(ServerPlayer player, Merchant merchant, MerchantOffer tradeOffer) + public void onTrade(final ServerPlayer player, final Merchant merchant, final MerchantOffer tradeOffer) { final RegistryAccess regs = player.getLevel().registryAccess(); - handler.call( () -> Arrays.asList( + handler.call(() -> Arrays.asList( new EntityValue(player), - merchant instanceof AbstractVillager ? new EntityValue((AbstractVillager) merchant) : Value.NULL, + merchant instanceof final AbstractVillager villager? new EntityValue(villager) : Value.NULL, ValueConversions.of(tradeOffer.getBaseCostA(), regs), ValueConversions.of(tradeOffer.getCostB(), regs), ValueConversions.of(tradeOffer.getResult(), regs) @@ -693,8 +724,9 @@ public class CarpetEventServer public static final Event PLAYER_PICKS_UP_ITEM = new Event("player_picks_up_item", 2, false) { @Override - public boolean onItemAction(ServerPlayer player, InteractionHand enumhand, ItemStack itemstack) { - handler.call( () -> Arrays.asList(new EntityValue(player), ValueConversions.of(itemstack, player.getLevel().registryAccess())), player::createCommandSourceStack); + public boolean onItemAction(final ServerPlayer player, final InteractionHand enumhand, final ItemStack itemstack) + { + handler.call(() -> Arrays.asList(new EntityValue(player), ValueConversions.of(itemstack, player.getLevel().registryAccess())), player::createCommandSourceStack); return false; } }; @@ -702,44 +734,44 @@ public class CarpetEventServer public static final Event PLAYER_ATTACKS_ENTITY = new Event("player_attacks_entity", 2, false) { @Override - public boolean onEntityHandAction(ServerPlayer player, Entity entity, InteractionHand enumhand) + public boolean onEntityHandAction(final ServerPlayer player, final Entity entity, final InteractionHand enumhand) { - return handler.call( () -> Arrays.asList(new EntityValue(player), new EntityValue(entity)), player::createCommandSourceStack); + return handler.call(() -> Arrays.asList(new EntityValue(player), new EntityValue(entity)), player::createCommandSourceStack); } }; public static final Event PLAYER_STARTS_SNEAKING = new Event("player_starts_sneaking", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_STOPS_SNEAKING = new Event("player_stops_sneaking", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_STARTS_SPRINTING = new Event("player_starts_sprinting", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_STOPS_SPRINTING = new Event("player_stops_sprinting", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; @@ -747,10 +779,10 @@ public class CarpetEventServer public static final Event PLAYER_RELEASED_ITEM = new Event("player_releases_item", 3, false) { @Override - public boolean onItemAction(ServerPlayer player, InteractionHand enumhand, ItemStack itemstack) + public boolean onItemAction(final ServerPlayer player, final InteractionHand enumhand, final ItemStack itemstack) { // this.getStackInHand(this.getActiveHand()), this.activeItemStack) - handler.call( () -> + handler.call(() -> Arrays.asList( new EntityValue(player), ValueConversions.of(itemstack, player.getLevel().registryAccess()), @@ -762,10 +794,10 @@ public class CarpetEventServer public static final Event PLAYER_FINISHED_USING_ITEM = new Event("player_finishes_using_item", 3, false) { @Override - public boolean onItemAction(ServerPlayer player, InteractionHand enumhand, ItemStack itemstack) + public boolean onItemAction(final ServerPlayer player, final InteractionHand enumhand, final ItemStack itemstack) { // this.getStackInHand(this.getActiveHand()), this.activeItemStack) - return handler.call( () -> + return handler.call(() -> Arrays.asList( new EntityValue(player), ValueConversions.of(itemstack, player.getLevel().registryAccess()), @@ -776,25 +808,25 @@ public class CarpetEventServer public static final Event PLAYER_DROPS_ITEM = new Event("player_drops_item", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - return handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + return handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); } }; public static final Event PLAYER_DROPS_STACK = new Event("player_drops_stack", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - return handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + return handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); } }; public static final Event PLAYER_CHOOSES_RECIPE = new Event("player_chooses_recipe", 3, false) { @Override - public boolean onRecipeSelected(ServerPlayer player, ResourceLocation recipe, boolean fullStack) + public boolean onRecipeSelected(final ServerPlayer player, final ResourceLocation recipe, final boolean fullStack) { - return handler.call( () -> + return handler.call(() -> Arrays.asList( new EntityValue(player), StringValue.of(NBTSerializableValue.nameFromRegistryId(recipe)), @@ -805,10 +837,13 @@ public class CarpetEventServer public static final Event PLAYER_SWITCHES_SLOT = new Event("player_switches_slot", 3, false) { @Override - public void onSlotSwitch(ServerPlayer player, int from, int to) + public void onSlotSwitch(final ServerPlayer player, final int from, final int to) { - if (from == to) return; // initial slot update - handler.call( () -> + if (from == to) + { + return; // initial slot update + } + handler.call(() -> Arrays.asList( new EntityValue(player), new NumericValue(from), @@ -819,19 +854,19 @@ public class CarpetEventServer public static final Event PLAYER_SWAPS_HANDS = new Event("player_swaps_hands", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - return handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + return handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); } }; public static final Event PLAYER_SWINGS_HAND = new Event("player_swings_hand", 2, false) { @Override - public void onHandAction(ServerPlayer player, InteractionHand hand) + public void onHandAction(final ServerPlayer player, final InteractionHand hand) { - handler.call( () -> Arrays.asList( - new EntityValue(player), - StringValue.of(hand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand") + handler.call(() -> Arrays.asList( + new EntityValue(player), + StringValue.of(hand == InteractionHand.MAIN_HAND ? "mainhand" : "offhand") ) , player::createCommandSourceStack); } @@ -839,24 +874,24 @@ public class CarpetEventServer public static final Event PLAYER_TAKES_DAMAGE = new Event("player_takes_damage", 4, false) { @Override - public boolean onDamage(Entity target, float amount, DamageSource source) + public boolean onDamage(final Entity target, final float amount, final DamageSource source) { - return handler.call( () -> + return handler.call(() -> Arrays.asList( - new EntityValue(target), - new NumericValue(amount), - StringValue.of(source.getMsgId()), - source.getEntity()==null?Value.NULL:new EntityValue(source.getEntity()) + new EntityValue(target), + new NumericValue(amount), + StringValue.of(source.getMsgId()), + source.getEntity() == null ? Value.NULL : new EntityValue(source.getEntity()) ), target::createCommandSourceStack); } }; public static final Event PLAYER_DEALS_DAMAGE = new Event("player_deals_damage", 3, false) { @Override - public boolean onDamage(Entity target, float amount, DamageSource source) + public boolean onDamage(final Entity target, final float amount, final DamageSource source) { - return handler.call( () -> - Arrays.asList(new EntityValue(source.getEntity()), new NumericValue(amount), new EntityValue(target)), + return handler.call(() -> + Arrays.asList(new EntityValue(source.getEntity()), new NumericValue(amount), new EntityValue(target)), () -> source.getEntity().createCommandSourceStack() ); } @@ -864,8 +899,9 @@ public class CarpetEventServer public static final Event PLAYER_COLLIDES_WITH_ENTITY = new Event("player_collides_with_entity", 2, false) { @Override - public boolean onEntityHandAction(ServerPlayer player, Entity entity, InteractionHand enumhand) { - handler.call( () -> Arrays.asList(new EntityValue(player), new EntityValue(entity)), player::createCommandSourceStack); + public boolean onEntityHandAction(final ServerPlayer player, final Entity entity, final InteractionHand enumhand) + { + handler.call(() -> Arrays.asList(new EntityValue(player), new EntityValue(entity)), player::createCommandSourceStack); return false; } }; @@ -873,86 +909,96 @@ public class CarpetEventServer public static final Event PLAYER_DIES = new Event("player_dies", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_RESPAWNS = new Event("player_respawns", 1, false) { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; public static final Event PLAYER_CHANGES_DIMENSION = new Event("player_changes_dimension", 5, false) { @Override - public void onDimensionChange(ServerPlayer player, Vec3 from, Vec3 to, ResourceKey fromDim, ResourceKey dimTo) + public void onDimensionChange(final ServerPlayer player, final Vec3 from, final Vec3 to, final ResourceKey fromDim, final ResourceKey dimTo) { // eligibility already checked in mixin - Value fromValue = ListValue.fromTriple(from.x, from.y, from.z); - Value toValue = (to == null)?Value.NULL:ListValue.fromTriple(to.x, to.y, to.z); - Value fromDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(fromDim.location())); - Value toDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(dimTo.location())); + final Value fromValue = ListValue.fromTriple(from.x, from.y, from.z); + final Value toValue = (to == null) ? Value.NULL : ListValue.fromTriple(to.x, to.y, to.z); + final Value fromDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(fromDim.location())); + final Value toDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(dimTo.location())); - handler.call( () -> Arrays.asList(new EntityValue(player), fromValue, fromDimStr, toValue, toDimStr), player::createCommandSourceStack); + handler.call(() -> Arrays.asList(new EntityValue(player), fromValue, fromDimStr, toValue, toDimStr), player::createCommandSourceStack); } }; - public static final Event PLAYER_CONNECTS = new Event("player_connects", 1, false) { + public static final Event PLAYER_CONNECTS = new Event("player_connects", 1, false) + { @Override - public boolean onPlayerEvent(ServerPlayer player) + public boolean onPlayerEvent(final ServerPlayer player) { - handler.call( () -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); + handler.call(() -> Collections.singletonList(new EntityValue(player)), player::createCommandSourceStack); return false; } }; - public static final Event PLAYER_DISCONNECTS = new Event("player_disconnects", 2, false) { + public static final Event PLAYER_DISCONNECTS = new Event("player_disconnects", 2, false) + { @Override - public boolean onPlayerMessage(ServerPlayer player, String message) + public boolean onPlayerMessage(final ServerPlayer player, final String message) { - handler.call( () -> Arrays.asList(new EntityValue(player), new StringValue(message)), player::createCommandSourceStack); + handler.call(() -> Arrays.asList(new EntityValue(player), new StringValue(message)), player::createCommandSourceStack); return false; } }; - public static final Event PLAYER_MESSAGE = new Event("player_message", 2, false) { + public static final Event PLAYER_MESSAGE = new Event("player_message", 2, false) + { @Override - public boolean onPlayerMessage(ServerPlayer player, String message) { - return handler.call( () -> Arrays.asList(new EntityValue(player), new StringValue(message)), player::createCommandSourceStack); + public boolean onPlayerMessage(final ServerPlayer player, final String message) + { + return handler.call(() -> Arrays.asList(new EntityValue(player), new StringValue(message)), player::createCommandSourceStack); } }; - public static final Event PLAYER_COMMAND = new Event("player_command", 2, false) { + public static final Event PLAYER_COMMAND = new Event("player_command", 2, false) + { @Override - public boolean onPlayerMessage(ServerPlayer player, String message) { - return handler.call( () -> Arrays.asList(new EntityValue(player), new StringValue(message)), player::createCommandSourceStack); + public boolean onPlayerMessage(final ServerPlayer player, final String message) + { + return handler.call(() -> Arrays.asList(new EntityValue(player), new StringValue(message)), player::createCommandSourceStack); } }; public static final Event STATISTICS = new Event("statistic", 4, false) { - private ResourceLocation getStatId(Stat stat) + private ResourceLocation getStatId(final Stat stat) { return stat.getType().getRegistry().getKey(stat.getValue()); } + private final Set skippedStats = Set.of( - Stats.TIME_SINCE_DEATH, - Stats.TIME_SINCE_REST, - //Stats.PLAY_ONE_MINUTE, - Stats.PLAY_TIME, - Stats.TOTAL_WORLD_TIME + Stats.TIME_SINCE_DEATH, + Stats.TIME_SINCE_REST, + Stats.PLAY_TIME, + Stats.TOTAL_WORLD_TIME ); + @Override - public void onPlayerStatistic(ServerPlayer player, Stat stat, int amount) + public void onPlayerStatistic(final ServerPlayer player, final Stat stat, final int amount) { - ResourceLocation id = getStatId(stat); - if (skippedStats.contains(id)) return; + final ResourceLocation id = getStatId(stat); + if (skippedStats.contains(id)) + { + return; + } final Registry> registry = player.getLevel().registryAccess().registryOrThrow(Registries.STAT_TYPE); - handler.call( () -> Arrays.asList( + handler.call(() -> Arrays.asList( new EntityValue(player), StringValue.of(NBTSerializableValue.nameFromRegistryId(registry.getKey(stat.getType()))), StringValue.of(NBTSerializableValue.nameFromRegistryId(id)), @@ -963,12 +1009,12 @@ public class CarpetEventServer public static final Event LIGHTNING = new Event("lightning", 2, true) { @Override - public void onWorldEventFlag(ServerLevel world, BlockPos pos, int flag) + public void onWorldEventFlag(final ServerLevel world, final BlockPos pos, final int flag) { handler.call( () -> Arrays.asList( new BlockValue(null, world, pos), - flag>0?Value.TRUE:Value.FALSE + flag > 0 ? Value.TRUE : Value.FALSE ), () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel(world) ); } @@ -976,31 +1022,49 @@ public class CarpetEventServer public static final Event CARPET_RULE_CHANGES = new Event("carpet_rule_changes", 2, true) { @Override - public void onCarpetRuleChanges(CarpetRule rule, CommandSourceStack source) + public void onCarpetRuleChanges(final CarpetRule rule, final CommandSourceStack source) { - String identifier = rule.settingsManager().identifier(); + final String identifier = rule.settingsManager().identifier(); final String namespace; - if (!identifier.equals("carpet")) + if (!identifier.equals("carpet")) { - namespace = identifier+":"; - } else { namespace = "";} + namespace = identifier + ":"; + } + else + { + namespace = ""; + } handler.call( () -> Arrays.asList( - new StringValue(namespace+rule.name()), + new StringValue(namespace + rule.name()), new StringValue(RuleHelper.toRuleString(rule.value())) ), () -> source ); } }; + //copy of Explosion.getCausingEntity() #TRACK# - private static LivingEntity getExplosionCausingEntity(Entity entity) + private static LivingEntity getExplosionCausingEntity(final Entity entity) { - if (entity == null) return null; - else if (entity instanceof PrimedTnt) return ((PrimedTnt)entity).getOwner(); - else if (entity instanceof LivingEntity) return (LivingEntity)entity; - else if (entity instanceof Projectile) { - Entity owner = ((Projectile)entity).getOwner(); - if (owner instanceof LivingEntity) return (LivingEntity)owner; + if (entity == null) + { + return null; + } + else if (entity instanceof final PrimedTnt tnt) + { + return tnt.getOwner(); + } + else if (entity instanceof final LivingEntity le) + { + return le; + } + else if (entity instanceof final Projectile p) + { + final Entity owner = p.getOwner(); + if (owner instanceof final LivingEntity le) + { + return le; + } } return null; } @@ -1008,18 +1072,18 @@ public class CarpetEventServer public static final Event EXPLOSION_OUTCOME = new Event("explosion_outcome", 8, true) { @Override - public void onExplosion(ServerLevel world, Entity e, Supplier attacker, double x, double y, double z, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) + public void onExplosion(final ServerLevel world, final Entity e, final Supplier attacker, final double x, final double y, final double z, final float power, final boolean createFire, final List affectedBlocks, final List affectedEntities, final Explosion.BlockInteraction type) { handler.call( () -> Arrays.asList( ListValue.fromTriple(x, y, z), NumericValue.of(power), EntityValue.of(e), - EntityValue.of(attacker!= null?attacker.get():Event.getExplosionCausingEntity(e)), + EntityValue.of(attacker != null ? attacker.get() : Event.getExplosionCausingEntity(e)), StringValue.of(type.name().toLowerCase(Locale.ROOT)), BooleanValue.of(createFire), - ListValue.wrap(affectedBlocks.stream().filter(b -> !world.isEmptyBlock(b)). map( // da heck they send air blocks - b -> new BlockValue(world.getBlockState(b),world,b) + ListValue.wrap(affectedBlocks.stream().filter(b -> !world.isEmptyBlock(b)).map( // da heck they send air blocks + b -> new BlockValue(world.getBlockState(b), world, b) )), ListValue.wrap(affectedEntities.stream().map(EntityValue::of)) ), () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel(world) @@ -1031,14 +1095,14 @@ public class CarpetEventServer public static final Event EXPLOSION = new Event("explosion", 6, true) { @Override - public void onExplosion(ServerLevel world, Entity e, Supplier attacker, double x, double y, double z, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) + public void onExplosion(final ServerLevel world, final Entity e, final Supplier attacker, final double x, final double y, final double z, final float power, final boolean createFire, final List affectedBlocks, final List affectedEntities, final Explosion.BlockInteraction type) { handler.call( () -> Arrays.asList( ListValue.fromTriple(x, y, z), NumericValue.of(power), EntityValue.of(e), - EntityValue.of(attacker!= null?attacker.get():Event.getExplosionCausingEntity(e)), + EntityValue.of(attacker != null ? attacker.get() : Event.getExplosionCausingEntity(e)), StringValue.of(type.name().toLowerCase(Locale.ROOT)), BooleanValue.of(createFire) ), () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel(world) @@ -1047,7 +1111,7 @@ public class CarpetEventServer }; @Deprecated - public static String getEntityLoadEventName(EntityType et) + public static String getEntityLoadEventName(final EntityType et) { return "entity_loaded_" + ValueConversions.of(BuiltInRegistries.ENTITY_TYPE.getKey(et)).getString(); } @@ -1058,7 +1122,7 @@ public class CarpetEventServer .map(et -> Map.entry(et, new Event(getEntityLoadEventName(et), 1, true, false) { @Override - public void onEntityAction(Entity entity, boolean created) + public void onEntityAction(final Entity entity, final boolean created) { handler.call( () -> Collections.singletonList(new EntityValue(entity)), @@ -1067,16 +1131,18 @@ public class CarpetEventServer } })).collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue)); - public static String getEntityHandlerEventName(EntityType et) + public static String getEntityHandlerEventName(final EntityType et) { return "entity_handler_" + ValueConversions.of(BuiltInRegistries.ENTITY_TYPE.getKey(et)).getString(); } public static final Map, Event> ENTITY_HANDLER = BuiltInRegistries.ENTITY_TYPE .stream() - .map(et -> Map.entry(et, new Event(getEntityHandlerEventName(et), 2, true, false) { + .map(et -> Map.entry(et, new Event(getEntityHandlerEventName(et), 2, true, false) + { @Override - public void onEntityAction(Entity entity, boolean created) { + public void onEntityAction(final Entity entity, final boolean created) + { handler.call( () -> Arrays.asList(new EntityValue(entity), BooleanValue.of(created)), () -> CarpetServer.minecraft_server.createCommandSourceStack().withLevel((ServerLevel) entity.level).withPermission(CarpetSettings.runPermissionLevel) @@ -1091,11 +1157,13 @@ public class CarpetEventServer public final CallbackList handler; public final boolean isPublic; // public events can be targetted with __on_ defs - public Event(String name, int reqArgs, boolean isGlobalOnly) + + public Event(final String name, final int reqArgs, final boolean isGlobalOnly) { this(name, reqArgs, isGlobalOnly, true); } - public Event(String name, int reqArgs, boolean isGlobalOnly, boolean isPublic) + + public Event(final String name, final int reqArgs, final boolean isGlobalOnly, final boolean isPublic) { this.name = name; this.handler = new CallbackList(reqArgs, true, isGlobalOnly); @@ -1103,34 +1171,43 @@ public class CarpetEventServer byName.put(name, this); } - public static List getAllEvents(CarpetScriptServer server, Predicate predicate) + public static List getAllEvents(final CarpetScriptServer server, final Predicate predicate) { - List eventList = new ArrayList<>(CarpetEventServer.Event.byName.values()); + final List eventList = new ArrayList<>(CarpetEventServer.Event.byName.values()); eventList.addAll(server.events.customEvents.values()); - if (predicate == null) return eventList; - return eventList.stream().filter(predicate).collect(Collectors.toList()); + if (predicate == null) + { + return eventList; + } + return eventList.stream().filter(predicate).toList(); } - public static Event getEvent(String name, CarpetScriptServer server) + public static Event getEvent(final String name, final CarpetScriptServer server) { - if (byName.containsKey(name)) return byName.get(name); + if (byName.containsKey(name)) + { + return byName.get(name); + } return server.events.customEvents.get(name); } - public static Event getOrCreateCustom(String name, CarpetScriptServer server) + public static Event getOrCreateCustom(final String name, final CarpetScriptServer server) { - Event event = getEvent(name, server); - if (event != null) return event; + final Event event = getEvent(name, server); + if (event != null) + { + return event; + } return new Event(name, server); } - public static void removeAllHostEvents(CarpetScriptHost host) + public static void removeAllHostEvents(final CarpetScriptHost host) { byName.values().forEach((e) -> e.handler.removeAllCalls(host)); host.scriptServer().events.customEvents.values().forEach((e) -> e.handler.removeAllCalls(host)); } - public static void transferAllHostEventsToChild(CarpetScriptHost host) + public static void transferAllHostEventsToChild(final CarpetScriptHost host) { byName.values().forEach((e) -> e.handler.createChildEvents(host)); host.scriptServer().events.customEvents.values().forEach((e) -> e.handler.createChildEvents(host)); @@ -1142,7 +1219,7 @@ public class CarpetEventServer } // custom event constructor - private Event(String name, CarpetScriptServer server) + private Event(final String name, final CarpetScriptServer server) { this.name = name; this.handler = new CallbackList(1, false, false); @@ -1157,41 +1234,126 @@ public class CarpetEventServer { return handler.callList.size() > 0; } - public boolean deprecated() {return false;} - //stubs for calls just to ease calls in vanilla code so they don't need to deal with scarpet value types - public void onTick() { } - public void onChunkEvent(ServerLevel world, ChunkPos chPos, boolean generated) { } - public boolean onPlayerEvent(ServerPlayer player) {return false;} - public boolean onPlayerMessage(ServerPlayer player, String message) {return false;} - public void onPlayerStatistic(ServerPlayer player, Stat stat, int amount) { } - public void onMountControls(ServerPlayer player, float strafeSpeed, float forwardSpeed, boolean jumping, boolean sneaking) { } - public boolean onItemAction(ServerPlayer player, InteractionHand enumhand, ItemStack itemstack) {return false;} - public boolean onBlockAction(ServerPlayer player, BlockPos blockpos, Direction facing) {return false;} - public boolean onBlockHit(ServerPlayer player, InteractionHand enumhand, BlockHitResult hitRes) {return false;} - public boolean onBlockBroken(ServerPlayer player, BlockPos pos, BlockState previousBS) {return false;} - public boolean onBlockPlaced(ServerPlayer player, BlockPos pos, InteractionHand enumhand, ItemStack itemstack) {return false;} - public boolean onEntityHandAction(ServerPlayer player, Entity entity, InteractionHand enumhand) {return false;} - public void onHandAction(ServerPlayer player, InteractionHand enumhand) { } - public void onEntityAction(Entity entity, boolean created) { } - public void onDimensionChange(ServerPlayer player, Vec3 from, Vec3 to, ResourceKey fromDim, ResourceKey dimTo) {} - public boolean onDamage(Entity target, float amount, DamageSource source) {return false;} - public boolean onRecipeSelected(ServerPlayer player, ResourceLocation recipe, boolean fullStack) {return false;} - public void onSlotSwitch(ServerPlayer player, int from, int to) {} - public void onTrade(ServerPlayer player, Merchant merchant, MerchantOffer tradeOffer) {} - public void onExplosion(ServerLevel world, Entity e, Supplier attacker, double x, double y, double z, float power, boolean createFire, List affectedBlocks, List affectedEntities, Explosion.BlockInteraction type) { } - public void onWorldEvent(ServerLevel world, BlockPos pos) { } - public void onWorldEventFlag(ServerLevel world, BlockPos pos, int flag) { } - public void onCarpetRuleChanges(CarpetRule rule, CommandSourceStack source) { } - public void onCustomPlayerEvent(ServerPlayer player, Object ... args) + public boolean deprecated() { - if (handler.reqArgs != (args.length+1)) - throw new InternalExpressionException("Expected "+handler.reqArgs+" arguments for "+name+", got "+(args.length+1)); + return false; + } + + //stubs for calls just to ease calls in vanilla code so they don't need to deal with scarpet value types + public void onTick() + { + } + + public void onChunkEvent(final ServerLevel world, final ChunkPos chPos, final boolean generated) + { + } + + public boolean onPlayerEvent(final ServerPlayer player) + { + return false; + } + + public boolean onPlayerMessage(final ServerPlayer player, final String message) + { + return false; + } + + public void onPlayerStatistic(final ServerPlayer player, final Stat stat, final int amount) + { + } + + public void onMountControls(final ServerPlayer player, final float strafeSpeed, final float forwardSpeed, final boolean jumping, final boolean sneaking) + { + } + + public boolean onItemAction(final ServerPlayer player, final InteractionHand enumhand, final ItemStack itemstack) + { + return false; + } + + public boolean onBlockAction(final ServerPlayer player, final BlockPos blockpos, final Direction facing) + { + return false; + } + + public boolean onBlockHit(final ServerPlayer player, final InteractionHand enumhand, final BlockHitResult hitRes) + { + return false; + } + + public boolean onBlockBroken(final ServerPlayer player, final BlockPos pos, final BlockState previousBS) + { + return false; + } + + public boolean onBlockPlaced(final ServerPlayer player, final BlockPos pos, final InteractionHand enumhand, final ItemStack itemstack) + { + return false; + } + + public boolean onEntityHandAction(final ServerPlayer player, final Entity entity, final InteractionHand enumhand) + { + return false; + } + + public void onHandAction(final ServerPlayer player, final InteractionHand enumhand) + { + } + + public void onEntityAction(final Entity entity, final boolean created) + { + } + + public void onDimensionChange(final ServerPlayer player, final Vec3 from, final Vec3 to, final ResourceKey fromDim, final ResourceKey dimTo) + { + } + + public boolean onDamage(final Entity target, final float amount, final DamageSource source) + { + return false; + } + + public boolean onRecipeSelected(final ServerPlayer player, final ResourceLocation recipe, final boolean fullStack) + { + return false; + } + + public void onSlotSwitch(final ServerPlayer player, final int from, final int to) + { + } + + public void onTrade(final ServerPlayer player, final Merchant merchant, final MerchantOffer tradeOffer) + { + } + + public void onExplosion(final ServerLevel world, final Entity e, final Supplier attacker, final double x, final double y, final double z, final float power, final boolean createFire, final List affectedBlocks, final List affectedEntities, final Explosion.BlockInteraction type) + { + } + + public void onWorldEvent(final ServerLevel world, final BlockPos pos) + { + } + + public void onWorldEventFlag(final ServerLevel world, final BlockPos pos, final int flag) + { + } + + public void onCarpetRuleChanges(final CarpetRule rule, final CommandSourceStack source) + { + } + + public void onCustomPlayerEvent(final ServerPlayer player, final Object... args) + { + if (handler.reqArgs != (args.length + 1)) + { + throw new InternalExpressionException("Expected " + handler.reqArgs + " arguments for " + name + ", got " + (args.length + 1)); + } handler.call( () -> { - List valArgs = new ArrayList<>(); + final List valArgs = new ArrayList<>(); valArgs.add(EntityValue.of(player)); - for (Object o: args) + for (final Object o : args) { valArgs.add(ValueConversions.guess(player.getLevel(), o)); } @@ -1199,14 +1361,17 @@ public class CarpetEventServer }, player::createCommandSourceStack ); } - public void onCustomWorldEvent(ServerLevel world, Object ... args) + + public void onCustomWorldEvent(final ServerLevel world, final Object... args) { if (handler.reqArgs != args.length) - throw new InternalExpressionException("Expected "+handler.reqArgs+" arguments for "+name+", got "+args.length); + { + throw new InternalExpressionException("Expected " + handler.reqArgs + " arguments for " + name + ", got " + args.length); + } handler.call( () -> { - List valArgs = new ArrayList<>(); - for (Object o: args) + final List valArgs = new ArrayList<>(); + for (final Object o : args) { valArgs.add(ValueConversions.guess(world, o)); } @@ -1217,7 +1382,7 @@ public class CarpetEventServer } - public CarpetEventServer(CarpetScriptServer scriptServer) + public CarpetEventServer(final CarpetScriptServer scriptServer) { this.scriptServer = scriptServer; Event.clearAllBuiltinEvents(); @@ -1226,12 +1391,14 @@ public class CarpetEventServer public void tick() { if (!TickSpeed.process_entities) - return; - Iterator eventIterator = scheduledCalls.iterator(); - List currentCalls = new ArrayList<>(); - while(eventIterator.hasNext()) { - ScheduledCall call = eventIterator.next(); + return; + } + final Iterator eventIterator = scheduledCalls.iterator(); + final List currentCalls = new ArrayList<>(); + while (eventIterator.hasNext()) + { + final ScheduledCall call = eventIterator.next(); call.dueTime--; if (call.dueTime <= 0) { @@ -1239,133 +1406,169 @@ public class CarpetEventServer eventIterator.remove(); } } - for (ScheduledCall call: currentCalls) + for (final ScheduledCall call : currentCalls) { call.execute(); } } - public void scheduleCall(CarpetContext context, FunctionValue function, List args, long due) + + public void scheduleCall(final CarpetContext context, final FunctionValue function, final List args, final long due) { scheduledCalls.add(new ScheduledCall(context, function, args, due)); } - public void runScheduledCall(BlockPos origin, CommandSourceStack source, String hostname, CarpetScriptHost host, FunctionValue udf, List argv) + public void runScheduledCall(final BlockPos origin, final CommandSourceStack source, final String hostname, final CarpetScriptHost host, final FunctionValue udf, final List argv) { if (hostname != null && !scriptServer.modules.containsKey(hostname)) // well - scheduled call app got unloaded + { return; + } try { host.callUDF(origin, source, udf, argv); } - catch (NullPointerException | InvalidCallbackException | IntegrityException ignored) { } + catch (final NullPointerException | InvalidCallbackException | IntegrityException ignored) + { + } } - public CallbackResult runEventCall(CommandSourceStack sender, String hostname, String optionalTarget, FunctionValue udf, List argv) + public CallbackResult runEventCall(final CommandSourceStack sender, final String hostname, final String optionalTarget, final FunctionValue udf, final List argv) { - CarpetScriptHost appHost = scriptServer.getAppHostByName(hostname); + final CarpetScriptHost appHost = scriptServer.getAppHostByName(hostname); // no such app - if (appHost == null) return CallbackResult.FAIL; + if (appHost == null) + { + return CallbackResult.FAIL; + } // dummy call for player apps that reside on the global copy - do not run them, but report as passes. - if (appHost.isPerUser() && optionalTarget==null) return CallbackResult.PASS; + if (appHost.isPerUser() && optionalTarget == null) + { + return CallbackResult.PASS; + } ServerPlayer target = null; if (optionalTarget != null) { target = sender.getServer().getPlayerList().getPlayerByName(optionalTarget); - if (target == null) return CallbackResult.FAIL; + if (target == null) + { + return CallbackResult.FAIL; + } + } + final CommandSourceStack source = sender.withPermission(CarpetSettings.runPermissionLevel); + final CarpetScriptHost executingHost = appHost.retrieveForExecution(sender, target); + if (executingHost == null) + { + return CallbackResult.FAIL; } - CommandSourceStack source = sender.withPermission(CarpetSettings.runPermissionLevel); - CarpetScriptHost executingHost = appHost.retrieveForExecution(sender, target); - if (executingHost == null) return CallbackResult.FAIL; try { - Value returnValue = executingHost.callUDF(source.withPermission(CarpetSettings.runPermissionLevel), udf, argv); + final Value returnValue = executingHost.callUDF(source.withPermission(CarpetSettings.runPermissionLevel), udf, argv); return returnValue instanceof StringValue && returnValue.getString().equals("cancel") ? CallbackResult.CANCEL : CallbackResult.SUCCESS; } - catch (NullPointerException | InvalidCallbackException | IntegrityException error) + catch (final NullPointerException | InvalidCallbackException | IntegrityException error) { CarpetScriptServer.LOG.error("Got exception when running event call ", error); return CallbackResult.FAIL; } } - public boolean addEventFromCommand(CommandSourceStack source, String event, String host, String funName) + public boolean addEventFromCommand(final CommandSourceStack source, final String event, final String host, final String funName) { - Event ev = Event.getEvent(event, CarpetServer.scriptServer); + final Event ev = Event.getEvent(event, CarpetServer.scriptServer); if (ev == null) { return false; } - boolean added = ev.handler.addFromExternal(source, host, funName, h -> onEventAddedToHost(ev, h)); - if (added) Messenger.m(source, "gi Added " + funName + " to " + event); + final boolean added = ev.handler.addFromExternal(source, host, funName, h -> onEventAddedToHost(ev, h)); + if (added) + { + Messenger.m(source, "gi Added " + funName + " to " + event); + } return added; } - public void addBuiltInEvent(String event, ScriptHost host, FunctionValue function, List args) + public void addBuiltInEvent(final String event, final ScriptHost host, final FunctionValue function, final List args) { // this is globals only - Event ev = Event.byName.get(event); + final Event ev = Event.byName.get(event); onEventAddedToHost(ev, host); - boolean success = ev.handler.addEventCallInternal(host, function, args==null?NOARGS:args); - if (!success) throw new InternalExpressionException("Global event "+event+" requires "+ev.handler.reqArgs+", not "+(function.getNumParams()-((args==null)?0:args.size()))); + final boolean success = ev.handler.addEventCallInternal(host, function, args == null ? NOARGS : args); + if (!success) + { + throw new InternalExpressionException("Global event " + event + " requires " + ev.handler.reqArgs + ", not " + (function.getNumParams() - ((args == null) ? 0 : args.size()))); + } } - public boolean handleCustomEvent(String event, CarpetScriptHost host, FunctionValue function, List args) + public boolean handleCustomEvent(final String event, final CarpetScriptHost host, final FunctionValue function, final List args) { - Event ev = Event.getOrCreateCustom(event, scriptServer); + final Event ev = Event.getOrCreateCustom(event, scriptServer); onEventAddedToHost(ev, host); - return ev.handler.addEventCallInternal(host, function, args==null?NOARGS:args); + return ev.handler.addEventCallInternal(host, function, args == null ? NOARGS : args); } - public int signalEvent(String event, CarpetContext cc, ServerPlayer optionalTarget, List callArgs) + public int signalEvent(final String event, final CarpetContext cc, final ServerPlayer optionalTarget, final List callArgs) { - Event ev = Event.getEvent(event, ((CarpetScriptHost)cc.host).scriptServer()); - if (ev == null) return -1; - return ev.handler.signal(cc.source(), optionalTarget, callArgs); + final Event ev = Event.getEvent(event, ((CarpetScriptHost) cc.host).scriptServer()); + return ev == null ? -1 : ev.handler.signal(cc.source(), optionalTarget, callArgs); } - private void onEventAddedToHost(Event event, ScriptHost host) + private void onEventAddedToHost(final Event event, final ScriptHost host) { - if (event.deprecated()) host.issueDeprecation(event.name+" event"); + if (event.deprecated()) + { + host.issueDeprecation(event.name + " event"); + } event.handler.sortByPriority(this.scriptServer); - //return !(event.globalOnly && (host.perUser || host.parent != null)); } - public boolean removeEventFromCommand(CommandSourceStack source, String event, String funName) + public boolean removeEventFromCommand(final CommandSourceStack source, final String event, final String funName) { - Event ev = Event.getEvent(event, CarpetServer.scriptServer); + final Event ev = Event.getEvent(event, CarpetServer.scriptServer); if (ev == null) { Messenger.m(source, "r Unknown event: " + event); return false; } - Callback.Signature call = Callback.fromString(funName); + final Callback.Signature call = Callback.fromString(funName); ev.handler.removeEventCall(call.host, call.target, call.function); // could verified if actually removed - Messenger.m(source, "gi Removed event: " + funName + " from "+event); + Messenger.m(source, "gi Removed event: " + funName + " from " + event); return true; } - public boolean removeBuiltInEvent(String event, CarpetScriptHost host) + + public boolean removeBuiltInEvent(final String event, final CarpetScriptHost host) { - Event ev = Event.getEvent(event, host.scriptServer()); - if (ev == null) return false; + final Event ev = Event.getEvent(event, host.scriptServer()); + if (ev == null) + { + return false; + } ev.handler.removeAllCalls(host); return true; } - public void removeBuiltInEvent(String event, CarpetScriptHost host, String funName) + public void removeBuiltInEvent(final String event, final CarpetScriptHost host, final String funName) { - Event ev = Event.getEvent(event, host.scriptServer()); - if (ev != null) ev.handler.removeEventCall(host.getName(), host.user, funName); + final Event ev = Event.getEvent(event, host.scriptServer()); + if (ev != null) + { + ev.handler.removeEventCall(host.getName(), host.user, funName); + } } - public void removeAllHostEvents(CarpetScriptHost host) + public void removeAllHostEvents(final CarpetScriptHost host) { // remove event handlers Event.removeAllHostEvents(host); if (host.isPerUser()) - for (ScriptHost child: host.userHosts.values()) Event.removeAllHostEvents((CarpetScriptHost) child); + { + for (final ScriptHost child : host.userHosts.values()) + { + Event.removeAllHostEvents((CarpetScriptHost) child); + } + } // remove scheduled calls scheduledCalls.removeIf(sc -> sc.host != null && sc.host.equals(host.getName())); } -} +} \ 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 6873ff6e..ef78a103 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -25,12 +25,24 @@ public class CarpetExpression private final CommandSourceStack source; private final BlockPos origin; private final Expression expr; - // these are for extensions - public Expression getExpr() {return expr;} - public CommandSourceStack getSource() {return source;} - public BlockPos getOrigin() {return origin;} - public CarpetExpression(Module module, String expression, CommandSourceStack source, BlockPos origin) + // these are for extensions + public Expression getExpr() + { + return expr; + } + + public CommandSourceStack getSource() + { + return source; + } + + public BlockPos getOrigin() + { + return origin; + } + + public CarpetExpression(final Module module, final String expression, final CommandSourceStack source, final BlockPos origin) { this.origin = origin; this.source = source; @@ -49,76 +61,80 @@ public class CarpetExpression CarpetServer.extensions.forEach(e -> e.scarpetApi(this)); } - public boolean fillAndScanCommand(ScriptHost host, int x, int y, int z) + public boolean fillAndScanCommand(final ScriptHost host, final int x, final int y, final int z) { if (CarpetServer.scriptServer.stopAll) + { return false; + } try { - Context context = new CarpetContext(host, source, origin). + final Context context = new CarpetContext(host, source, origin). with("x", (c, t) -> new NumericValue(x - origin.getX()).bindTo("x")). with("y", (c, t) -> new NumericValue(y - origin.getY()).bindTo("y")). with("z", (c, t) -> new NumericValue(z - origin.getZ()).bindTo("z")). with("_", (c, t) -> new BlockValue(null, source.getLevel(), new BlockPos(x, y, z)).bindTo("_")); - Entity e = source.getEntity(); - if (e==null) + final Entity e = source.getEntity(); + if (e == null) { - Value nullPlayer = Value.NULL.reboundedTo("p"); - context.with("p", (cc, tt) -> nullPlayer ); + final Value nullPlayer = Value.NULL.reboundedTo("p"); + context.with("p", (cc, tt) -> nullPlayer); } else { - Value playerValue = new EntityValue(e).bindTo("p"); + final Value playerValue = new EntityValue(e).bindTo("p"); context.with("p", (cc, tt) -> playerValue); } - return CarpetServer.scriptServer.events.handleEvents.getWhileDisabled(()-> this.expr.eval(context).getBoolean()); + return CarpetServer.scriptServer.events.handleEvents.getWhileDisabled(() -> this.expr.eval(context).getBoolean()); } - catch (ExpressionException e) + catch (final ExpressionException e) { throw new CarpetExpressionException(e.getMessage(), e.stack); } - catch (ArithmeticException ae) + catch (final ArithmeticException ae) { - throw new CarpetExpressionException("Math doesn't compute... "+ae.getMessage(), null); + throw new CarpetExpressionException("Math doesn't compute... " + ae.getMessage(), null); } - catch (StackOverflowError soe) + catch (final StackOverflowError soe) { throw new CarpetExpressionException("Your thoughts are too deep", null); } } - public Value scriptRunCommand(ScriptHost host, BlockPos pos) + public Value scriptRunCommand(final ScriptHost host, final BlockPos pos) { if (CarpetServer.scriptServer.stopAll) + { throw new CarpetExpressionException("SCRIPTING PAUSED (unpause with /script resume)", null); + } try { - Context context = new CarpetContext(host, source, origin). + final Context context = new CarpetContext(host, source, origin). with("x", (c, t) -> new NumericValue(pos.getX() - origin.getX()).bindTo("x")). with("y", (c, t) -> new NumericValue(pos.getY() - origin.getY()).bindTo("y")). with("z", (c, t) -> new NumericValue(pos.getZ() - origin.getZ()).bindTo("z")); - Entity e = source.getEntity(); - if (e==null) + final Entity e = source.getEntity(); + if (e == null) { - Value nullPlayer = Value.NULL.reboundedTo("p"); - context.with("p", (cc, tt) -> nullPlayer ); + final Value nullPlayer = Value.NULL.reboundedTo("p"); + context.with("p", (cc, tt) -> nullPlayer); } else { - Value playerValue = new EntityValue(e).bindTo("p"); + final Value playerValue = new EntityValue(e).bindTo("p"); context.with("p", (cc, tt) -> playerValue); } - return CarpetServer.scriptServer.events.handleEvents.getWhileDisabled(()-> this.expr.eval(context)); + return CarpetServer.scriptServer.events.handleEvents.getWhileDisabled(() -> this.expr.eval(context)); } - catch (ExpressionException e) + catch (final ExpressionException e) { throw new CarpetExpressionException(e.getMessage(), e.stack); } - catch (ArithmeticException ae) + catch (final ArithmeticException ae) { - throw new CarpetExpressionException("Math doesn't compute... "+ae.getMessage(), null); + throw new CarpetExpressionException("Math doesn't compute... " + ae.getMessage(), null); } - catch (StackOverflowError soe) + catch (final StackOverflowError soe) { throw new CarpetExpressionException("Your thoughts are too deep", null); } diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index 7462db75..64a46da0 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -85,7 +85,7 @@ public class CarpetScriptHost extends ScriptHost public AppStoreManager.StoreNode storeSource; boolean hasCommand; - private CarpetScriptHost(CarpetScriptServer server, Module code, boolean perUser, ScriptHost parent, Map config, Map argTypes, Predicate commandValidator, boolean isRuleApp) + private CarpetScriptHost(final CarpetScriptServer server, final Module code, final boolean perUser, final ScriptHost parent, final Map config, final Map argTypes, final Predicate commandValidator, final boolean isRuleApp) { super(code, server, perUser, parent); this.saveTimeout = 0; @@ -96,7 +96,7 @@ public class CarpetScriptHost extends ScriptHost } else if (parent != null) { - persistenceRequired = ((CarpetScriptHost)parent).persistenceRequired; + persistenceRequired = ((CarpetScriptHost) parent).persistenceRequired; strict = parent.strict; } appConfig = config; @@ -106,31 +106,31 @@ public class CarpetScriptHost extends ScriptHost storeSource = null; } - public static CarpetScriptHost create(CarpetScriptServer scriptServer, Module module, boolean perPlayer, CommandSourceStack source, Predicate commandValidator, boolean isRuleApp, AppStoreManager.StoreNode storeSource) + public static CarpetScriptHost create(final CarpetScriptServer scriptServer, final Module module, final boolean perPlayer, final CommandSourceStack source, final Predicate commandValidator, final boolean isRuleApp, final AppStoreManager.StoreNode storeSource) { - CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>(), commandValidator, isRuleApp); + final CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>(), commandValidator, isRuleApp); // parse code and convert to expression if (module != null) { try { host.setChatErrorSnooper(source); - CarpetExpression ex = new CarpetExpression(host.main, module.code(), source, new BlockPos(0, 0, 0)); + final CarpetExpression ex = new CarpetExpression(host.main, module.code(), source, new BlockPos(0, 0, 0)); ex.getExpr().asATextSource(); host.storeSource = storeSource; ex.scriptRunCommand(host, new BlockPos(source.getPosition())); } - catch (CarpetExpressionException e) + catch (final CarpetExpressionException e) { host.handleErrorWithStack("Error while evaluating expression", e); throw new LoadException(); } - catch (ArithmeticException ae) // is this branch ever reached? Seems like arithmetic exceptions are converted to CEEs earlier + catch (final ArithmeticException ae) // is this branch ever reached? Seems like arithmetic exceptions are converted to CEEs earlier { host.handleErrorWithStack("Math doesn't compute", ae); throw new LoadException(); } - catch (StackOverflowError soe) + catch (final StackOverflowError soe) { host.handleErrorWithStack("Your thoughts are too deep", soe); } @@ -142,42 +142,44 @@ public class CarpetScriptHost extends ScriptHost return host; } - private static int execute(CommandContext ctx, String hostName, FunctionArgument funcSpec, List paramNames) throws CommandSyntaxException + private static int execute(final CommandContext ctx, final String hostName, final FunctionArgument funcSpec, final List paramNames) throws CommandSyntaxException { - CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); - CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(ctx.getSource()); - List argNames = funcSpec.function.getArguments(); - if ((argNames.size()-funcSpec.args.size()) != paramNames.size()) - throw new SimpleCommandExceptionType(Component.literal("Target function "+funcSpec.function.getPrettyString()+" as wrong number of arguments, required "+paramNames.size()+", found "+argNames.size()+" with "+funcSpec.args.size()+" provided")).create(); - List args = new ArrayList<>(argNames.size()); - for (String s : paramNames) + final CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); + final CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(ctx.getSource()); + final List argNames = funcSpec.function.getArguments(); + if ((argNames.size() - funcSpec.args.size()) != paramNames.size()) + { + throw new SimpleCommandExceptionType(Component.literal("Target function " + funcSpec.function.getPrettyString() + " as wrong number of arguments, required " + paramNames.size() + ", found " + argNames.size() + " with " + funcSpec.args.size() + " provided")).create(); + } + final List args = new ArrayList<>(argNames.size()); + for (final String s : paramNames) { args.add(CommandArgument.getValue(ctx, s, cHost)); } args.addAll(funcSpec.args); - Value response = cHost.handleCommand(ctx.getSource(), funcSpec.function, args); - // will skip prints for new - //if (!response.isNull()) Messenger.m(ctx.getSource(), "gi " + response.getString()); - int intres = (int) response.readInteger(); + final Value response = cHost.handleCommand(ctx.getSource(), funcSpec.function, args); + final int intres = (int) response.readInteger(); CarpetProfiler.end_current_section(currentSection); return intres; } public LiteralArgumentBuilder addPathToCommand( - LiteralArgumentBuilder command, - List path, - FunctionArgument functionSpec + final LiteralArgumentBuilder command, + final List path, + final FunctionArgument functionSpec ) throws CommandSyntaxException { - String hostName = main.name(); - List commandArgs = path.stream().filter(t -> t.isArgument).map(t -> t.surface).collect(Collectors.toList()); - if (commandArgs.size() != (functionSpec.function.getNumParams()-functionSpec.args.size()) ) - throw CommandArgument.error("Number of parameters in function "+functionSpec.function.fullName()+" doesn't match parameters for a command"); + final String hostName = main.name(); + final List commandArgs = path.stream().filter(t -> t.isArgument).map(t -> t.surface).collect(Collectors.toList()); + if (commandArgs.size() != (functionSpec.function.getNumParams() - functionSpec.args.size())) + { + throw CommandArgument.error("Number of parameters in function " + functionSpec.function.fullName() + " doesn't match parameters for a command"); + } if (path.isEmpty()) { return command.executes((c) -> execute(c, hostName, functionSpec, Collections.emptyList())); } - List reversedPath = new ArrayList<>(path); + final List reversedPath = new ArrayList<>(path); Collections.reverse(reversedPath); ArgumentBuilder argChain = reversedPath.get(0).getCommandNode(this).executes(c -> execute(c, hostName, functionSpec, commandArgs)); for (int i = 1; i < reversedPath.size(); i++) @@ -188,14 +190,14 @@ public class CarpetScriptHost extends ScriptHost } public LiteralArgumentBuilder getNewCommandTree( - List,FunctionArgument>> entries, Predicate useValidator + final List, FunctionArgument>> entries, final Predicate useValidator ) throws CommandSyntaxException { - String hostName = main.name(); - Predicate configValidator = getCommandConfigPermissions(); + final String hostName = main.name(); + final Predicate configValidator = getCommandConfigPermissions(); LiteralArgumentBuilder command = literal(hostName). - requires((player) -> useValidator.test(player) && configValidator.test(player)); - for (Pair,FunctionArgument> commandData : entries) + requires((player) -> useValidator.test(player) && configValidator.test(player)); + for (final Pair, FunctionArgument> commandData : entries) { command = this.addPathToCommand(command, commandData.getKey(), commandData.getValue()); } @@ -204,45 +206,51 @@ public class CarpetScriptHost extends ScriptHost public Predicate getCommandConfigPermissions() throws CommandSyntaxException { - Value confValue = appConfig.get(StringValue.of("command_permission")); - if (confValue == null) return s -> true; - if (confValue instanceof NumericValue) + final Value confValue = appConfig.get(StringValue.of("command_permission")); + if (confValue == null) { - int level = ((NumericValue) confValue).getInt(); - if (level < 1 || level > 4) throw CommandArgument.error("Numeric permission level for custom commands should be between 1 and 4"); + return s -> true; + } + if (confValue instanceof final NumericValue number) + { + final int level = number.getInt(); + if (level < 1 || level > 4) + { + throw CommandArgument.error("Numeric permission level for custom commands should be between 1 and 4"); + } return s -> s.hasPermission(level); } - if (!(confValue instanceof FunctionValue)) + if (!(confValue instanceof final FunctionValue fun)) { - String perm = confValue.getString().toLowerCase(Locale.ROOT); - switch (perm) - { - case "ops": return s -> s.hasPermission(2); - case "server": return s -> !(s.getEntity() instanceof ServerPlayer); - case "players": return s -> s.getEntity() instanceof ServerPlayer; - case "all": return s -> true; - default: throw CommandArgument.error("Unknown command permission: "+perm); - } + final String perm = confValue.getString().toLowerCase(Locale.ROOT); + return switch (perm) { + case "ops" -> s -> s.hasPermission(2); + case "server" -> s -> !(s.getEntity() instanceof ServerPlayer); + case "players" -> s -> s.getEntity() instanceof ServerPlayer; + case "all" -> s -> true; + default -> throw CommandArgument.error("Unknown command permission: " + perm); + }; } - FunctionValue fun = (FunctionValue) confValue; - if (fun.getNumParams() != 1) throw CommandArgument.error("Custom command permission function should expect 1 argument"); - String hostName = getName(); + if (fun.getNumParams() != 1) + { + throw CommandArgument.error("Custom command permission function should expect 1 argument"); + } + final String hostName = getName(); return s -> { try { - CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); - CarpetScriptHost cHost = null; - cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(s); - Value response = cHost.handleCommand(s, fun, Collections.singletonList( - (s.getEntity() instanceof ServerPlayer)?new EntityValue(s.getEntity()):Value.NULL) + final CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); + final CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(s); + final Value response = cHost.handleCommand(s, fun, Collections.singletonList( + (s.getEntity() instanceof ServerPlayer) ? new EntityValue(s.getEntity()) : Value.NULL) ); - boolean res = response.getBoolean(); + final boolean res = response.getBoolean(); CarpetProfiler.end_current_section(currentSection); return res; } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { - Messenger.m(s, "rb Unable to run app command: "+e.getMessage()); + Messenger.m(s, "rb Unable to run app command: " + e.getMessage()); return false; } }; @@ -255,35 +263,45 @@ public class CarpetScriptHost extends ScriptHost } @Override - protected void setupUserHost(ScriptHost host) + protected void setupUserHost(final ScriptHost host) { super.setupUserHost(host); // transfer Events - CarpetScriptHost child = (CarpetScriptHost) host; + final CarpetScriptHost child = (CarpetScriptHost) host; CarpetEventServer.Event.transferAllHostEventsToChild(child); - FunctionValue onStart = child.getFunction("__on_start"); - if (onStart != null) child.callNow(onStart, Collections.emptyList()); + final FunctionValue onStart = child.getFunction("__on_start"); + if (onStart != null) + { + child.callNow(onStart, Collections.emptyList()); + } } @Override - public void addUserDefinedFunction(Context ctx, Module module, String funName, FunctionValue function) + public void addUserDefinedFunction(final Context ctx, final Module module, final String funName, final FunctionValue function) { super.addUserDefinedFunction(ctx, module, funName, function); - if (ctx.host.main != module) return; // not dealing with automatic imports / exports /configs / apps from imports + if (ctx.host.main != module) + { + return; // not dealing with automatic imports / exports /configs / apps from imports + } if (funName.startsWith("__")) // potential fishy activity { if (funName.startsWith("__on_")) // here we can make a determination if we want to only accept events from main module. { // this is nasty, we have the host and function, yet we add it via names, but hey - works for now - String event = funName.replaceFirst("__on_", ""); + final String event = funName.replaceFirst("__on_", ""); if (CarpetEventServer.Event.byName.containsKey(event)) + { scriptServer().events.addBuiltInEvent(event, this, function, null); + } } else if (funName.equals("__config")) { // needs to be added as we read the code, cause other events may be affected. if (!readConfig()) + { throw new InternalExpressionException("Invalid app config (via '__config()' function)"); + } } } } @@ -292,43 +310,57 @@ public class CarpetScriptHost extends ScriptHost { try { - FunctionValue configFunction = getFunction("__config"); - if (configFunction == null) return false; - Value ret = callNow(configFunction, Collections.emptyList()); - if (!(ret instanceof MapValue)) return false; - Map config = ((MapValue) ret).getMap(); + final FunctionValue configFunction = getFunction("__config"); + if (configFunction == null) + { + return false; + } + final Value ret = callNow(configFunction, Collections.emptyList()); + if (!(ret instanceof final MapValue map)) + { + return false; + } + final Map config = map.getMap(); setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player")); persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.TRUE).getBoolean(); strict = config.getOrDefault(StringValue.of("strict"), Value.FALSE).getBoolean(); eventPriority = config.getOrDefault(new StringValue("event_priority"), Value.ZERO).readDoubleNumber(); // check requires - Value loadRequirements = config.get(new StringValue("requires")); - if (loadRequirements instanceof FunctionValue) + final Value loadRequirements = config.get(new StringValue("requires")); + if (loadRequirements instanceof final FunctionValue functionValue) { - Value reqResult = callNow((FunctionValue) loadRequirements, Collections.emptyList()); + final Value reqResult = callNow(functionValue, Collections.emptyList()); if (reqResult.getBoolean()) // != false or null + { throw new LoadException(reqResult.getString()); + } } else { checkModVersionRequirements(loadRequirements); - }; + } if (storeSource != null) { - Value resources = config.get(new StringValue("resources")); + final Value resources = config.get(new StringValue("resources")); if (resources != null) { - if (!(resources instanceof ListValue)) throw new InternalExpressionException("App resources not defined as a list"); - for (Value resource : ((ListValue) resources).getItems()) + if (!(resources instanceof final ListValue list)) + { + throw new InternalExpressionException("App resources not defined as a list"); + } + for (final Value resource : list.getItems()) { AppStoreManager.addResource(this, storeSource, resource); } } - Value libraries = config.get(new StringValue("libraries")); + final Value libraries = config.get(new StringValue("libraries")); if (libraries != null) { - if (!(libraries instanceof ListValue)) throw new InternalExpressionException("App libraries not defined as a list"); - for (Value library : ((ListValue) libraries).getItems()) + if (!(libraries instanceof final ListValue list)) + { + throw new InternalExpressionException("App libraries not defined as a list"); + } + for (final Value library : list.getItems()) { AppStoreManager.addLibrary(this, storeSource, library); } @@ -336,22 +368,25 @@ public class CarpetScriptHost extends ScriptHost } appConfig = config; } - catch (NullPointerException ignored) + catch (final NullPointerException ignored) { return false; } return true; } - static class ListComparator> implements Comparator,?>> + static class ListComparator> implements Comparator, ?>> { @Override - public int compare(Pair,?> p1, Pair,?> p2) { - List o1 = p1.getKey(); - List o2 = p2.getKey(); - for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) { - int c = o1.get(i).compareTo(o2.get(i)); - if (c != 0) { + public int compare(final Pair, ?> p1, final Pair, ?> p2) + { + final List o1 = p1.getKey(); + final List o2 = p2.getKey(); + for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) + { + final int c = o1.get(i).compareTo(o2.get(i)); + if (c != 0) + { return c; } } @@ -360,7 +395,8 @@ public class CarpetScriptHost extends ScriptHost } // Used to ensure app gets marked as holding command from a central place - private void registerCommand(LiteralArgumentBuilder command) { + private void registerCommand(final LiteralArgumentBuilder command) + { scriptServer().server.getCommands().getDispatcher().register(command); hasCommand = true; } @@ -368,32 +404,37 @@ public class CarpetScriptHost extends ScriptHost public void readCustomArgumentTypes() throws CommandSyntaxException { // read custom arguments - Value arguments = appConfig.get(StringValue.of("arguments")); + final Value arguments = appConfig.get(StringValue.of("arguments")); if (arguments != null) { - if (!(arguments instanceof MapValue)) - throw CommandArgument.error("'arguments' element in config should be a map"); - appArgTypes.clear(); - for (Map.Entry typeData : ((MapValue)arguments).getMap().entrySet()) + if (!(arguments instanceof final MapValue map)) { - String argument = typeData.getKey().getString(); - Value spec = typeData.getValue(); - if (!(spec instanceof MapValue)) throw CommandArgument.error("Spec for '"+argument+"' should be a map"); - Map specData = ((MapValue) spec).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue)); + throw CommandArgument.error("'arguments' element in config should be a map"); + } + appArgTypes.clear(); + for (final Map.Entry typeData : map.getMap().entrySet()) + { + final String argument = typeData.getKey().getString(); + final Value spec = typeData.getValue(); + if (!(spec instanceof final MapValue specMap)) + { + throw CommandArgument.error("Spec for '" + argument + "' should be a map"); + } + final Map specData = specMap.getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue)); appArgTypes.put(argument, CommandArgument.buildFromConfig(argument, specData, this)); } } } - public Boolean addAppCommands(Consumer notifier) + public Boolean addAppCommands(final Consumer notifier) { try { readCustomArgumentTypes(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { - notifier.accept(Messenger.c("r Error when handling of setting up custom argument types: "+e.getMessage())); + notifier.accept(Messenger.c("r Error when handling of setting up custom argument types: " + e.getMessage())); return false; } if (appConfig.get(StringValue.of("commands")) != null) @@ -405,17 +446,15 @@ public class CarpetScriptHost extends ScriptHost } try { - LiteralArgumentBuilder command = readCommands(commandValidator); + final LiteralArgumentBuilder command = readCommands(commandValidator); if (command != null) { registerCommand(command); return true; } - else { - return false; - } + return false; } - catch (CommandSyntaxException cse) + catch (final CommandSyntaxException cse) { // failed notifier.accept(Messenger.c("r Failed to build command system: ", cse.getRawMessage())); @@ -425,30 +464,36 @@ public class CarpetScriptHost extends ScriptHost } return addLegacyCommand(notifier); } - - public void checkModVersionRequirements(Value reqs) { + + public void checkModVersionRequirements(final Value reqs) + { if (reqs == null) + { return; - if (!(reqs instanceof MapValue)) + } + if (!(reqs instanceof final MapValue map)) { throw new InternalExpressionException("`requires` field must be a map of mod dependencies or a function to be executed"); } - Map requirements = ((MapValue)reqs).getMap(); - for (Entry requirement : requirements.entrySet()) + final Map requirements = map.getMap(); + for (final Entry requirement : requirements.entrySet()) { - String requiredModId = requirement.getKey().getString(); - String stringPredicate = requirement.getValue().getString(); - VersionPredicate predicate; - try { + final String requiredModId = requirement.getKey().getString(); + final String stringPredicate = requirement.getValue().getString(); + final VersionPredicate predicate; + try + { predicate = VersionPredicate.parse(stringPredicate); - } catch (VersionParsingException e) { + } + catch (final VersionParsingException e) + { throw new InternalExpressionException("Failed to parse version conditions for '" + requiredModId + "' in 'requires': " + e.getMessage()); } - ModContainer mod = FabricLoader.getInstance().getModContainer(requiredModId).orElse(null); + final ModContainer mod = FabricLoader.getInstance().getModContainer(requiredModId).orElse(null); if (mod != null) { - Version presentVersion = mod.getMetadata().getVersion(); + final Version presentVersion = mod.getMetadata().getVersion(); if (predicate.test(presentVersion) || (FabricLoader.getInstance().isDevelopmentEnvironment() && !(presentVersion instanceof SemanticVersion))) { // in a dev env, mod version is usually replaced with ${version}, and that isn't semantic continue; @@ -458,10 +503,12 @@ public class CarpetScriptHost extends ScriptHost } } - private Boolean addLegacyCommand(Consumer notifier) + private Boolean addLegacyCommand(final Consumer notifier) { - if (main == null) return false; - if (getFunction("__command") == null) return false; + if (main == null || getFunction("__command") == null) + { + return false; + } if (scriptServer().isInvalidCommandRoot(getName())) { @@ -469,43 +516,46 @@ public class CarpetScriptHost extends ScriptHost return null; } - Predicate configValidator; + final Predicate configValidator; try { configValidator = getCommandConfigPermissions(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { - notifier.accept(Messenger.c("rb "+e.getMessage())); + notifier.accept(Messenger.c("rb " + e.getMessage())); return null; } - String hostName = getName(); + final String hostName = getName(); LiteralArgumentBuilder command = literal(hostName). requires((player) -> commandValidator.test(player) && configValidator.test(player)). - executes( (c) -> + executes((c) -> { - CarpetScriptHost targetHost = scriptServer().modules.get(hostName).retrieveOwnForExecution(c.getSource()); - Value response = targetHost.handleCommandLegacy(c.getSource(),"__command", null, ""); - if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString()); - return (int)response.readInteger(); + final CarpetScriptHost targetHost = scriptServer().modules.get(hostName).retrieveOwnForExecution(c.getSource()); + final Value response = targetHost.handleCommandLegacy(c.getSource(), "__command", null, ""); + if (!response.isNull()) + { + Messenger.m(c.getSource(), "gi " + response.getString()); + } + return (int) response.readInteger(); }); - boolean hasTypeSupport = appConfig.getOrDefault(StringValue.of("legacy_command_type_support"), Value.FALSE).getBoolean(); + final boolean hasTypeSupport = appConfig.getOrDefault(StringValue.of("legacy_command_type_support"), Value.FALSE).getBoolean(); - for (String function : globalFunctionNames(main, s -> !s.startsWith("_")).sorted().collect(Collectors.toList())) + for (final String function : globalFunctionNames(main, s -> !s.startsWith("_")).sorted().collect(Collectors.toList())) { if (hasTypeSupport) { try { - FunctionValue functionValue = getFunction(function); + final FunctionValue functionValue = getFunction(function); command = addPathToCommand( command, CommandToken.parseSpec(CommandToken.specFromSignature(functionValue), this), FunctionArgument.fromCommandSpec(this, functionValue) ); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { return false; } @@ -516,17 +566,23 @@ public class CarpetScriptHost extends ScriptHost then(literal(function). requires((player) -> scriptServer().modules.get(hostName).getFunction(function) != null). executes((c) -> { - CarpetScriptHost targetHost = scriptServer().modules.get(hostName).retrieveOwnForExecution(c.getSource()); - Value response = targetHost.handleCommandLegacy(c.getSource(),function, null, ""); - if (!response.isNull()) Messenger.m(c.getSource(), "gi " + response.getString()); + final CarpetScriptHost targetHost = scriptServer().modules.get(hostName).retrieveOwnForExecution(c.getSource()); + final Value response = targetHost.handleCommandLegacy(c.getSource(), function, null, ""); + if (!response.isNull()) + { + Messenger.m(c.getSource(), "gi " + response.getString()); + } return (int) response.readInteger(); }). then(argument("args...", StringArgumentType.greedyString()). - executes( (c) -> { - CarpetScriptHost targetHost = scriptServer().modules.get(hostName).retrieveOwnForExecution(c.getSource()); - Value response = targetHost.handleCommandLegacy(c.getSource(),function, null, StringArgumentType.getString(c, "args...")); - if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString()); - return (int)response.readInteger(); + executes((c) -> { + final CarpetScriptHost targetHost = scriptServer().modules.get(hostName).retrieveOwnForExecution(c.getSource()); + final Value response = targetHost.handleCommandLegacy(c.getSource(), function, null, StringArgumentType.getString(c, "args...")); + if (!response.isNull()) + { + Messenger.m(c.getSource(), "gi " + response.getString()); + } + return (int) response.readInteger(); }))); } } @@ -534,39 +590,48 @@ public class CarpetScriptHost extends ScriptHost return true; } - public LiteralArgumentBuilder readCommands(Predicate useValidator) throws CommandSyntaxException + public LiteralArgumentBuilder readCommands(final Predicate useValidator) throws CommandSyntaxException { - Value commands = appConfig.get(StringValue.of("commands")); + final Value commands = appConfig.get(StringValue.of("commands")); - if (commands == null) return null; - if (!(commands instanceof MapValue)) - throw CommandArgument.error("'commands' element in config should be a map"); - List,FunctionArgument>> commandEntries = new ArrayList<>(); - - for (Map.Entry commandsData : ((MapValue)commands).getMap().entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList())) + if (commands == null) { - List elements = CommandToken.parseSpec(commandsData.getKey().getString(), this); - FunctionArgument funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue()); + return null; + } + if (!(commands instanceof final MapValue map)) + { + throw CommandArgument.error("'commands' element in config should be a map"); + } + final List, FunctionArgument>> commandEntries = new ArrayList<>(); + + for (final Map.Entry commandsData : map.getMap().entrySet().stream().sorted(Entry.comparingByKey()).toList()) + { + final List elements = CommandToken.parseSpec(commandsData.getKey().getString(), this); + final FunctionArgument funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue()); commandEntries.add(Pair.of(elements, funSpec)); } commandEntries.sort(new ListComparator<>()); if (!appConfig.getOrDefault(StringValue.of("allow_command_conflicts"), Value.FALSE).getBoolean()) { - for (int i = 0; i < commandEntries.size()-1; i++) + for (int i = 0; i < commandEntries.size() - 1; i++) { - List first = commandEntries.get(i).getKey(); - List other = commandEntries.get(i+1).getKey(); - int checkSize = Math.min(first.size(), other.size()); + final List first = commandEntries.get(i).getKey(); + final List other = commandEntries.get(i + 1).getKey(); + final int checkSize = Math.min(first.size(), other.size()); for (int t = 0; t < checkSize; t++) { - CommandToken tik = first.get(t); - CommandToken tok = other.get(t); + final CommandToken tik = first.get(t); + final CommandToken tok = other.get(t); if (tik.isArgument && tok.isArgument && !tik.surface.equals(tok.surface)) - throw CommandArgument.error("Conflicting commands: \n"+ - " - [" +first.stream().map(tt -> tt.surface).collect(Collectors.joining(" ")) + "] at "+tik.surface+"\n"+ - " - [" +other.stream().map(tt -> tt.surface).collect(Collectors.joining(" ")) + "] at "+tok.surface+"\n"); + { + throw CommandArgument.error("Conflicting commands: \n" + + " - [" + first.stream().map(tt -> tt.surface).collect(Collectors.joining(" ")) + "] at " + tik.surface + "\n" + + " - [" + other.stream().map(tt -> tt.surface).collect(Collectors.joining(" ")) + "] at " + tok.surface + "\n"); + } if (!tik.equals(tok)) + { break; + } } } } @@ -574,37 +639,39 @@ public class CarpetScriptHost extends ScriptHost } @Override - protected Module getModuleOrLibraryByName(String name) + protected Module getModuleOrLibraryByName(final String name) { - Module module = scriptServer().getModule(name, true); + final Module module = scriptServer().getModule(name, true); if (module == null) - throw new InternalExpressionException("Unable to locate package: "+name); + { + throw new InternalExpressionException("Unable to locate package: " + name); + } return module; } @Override - protected void runModuleCode(Context c, Module module) + protected void runModuleCode(final Context c, final Module module) { - CarpetContext cc = (CarpetContext)c; - CarpetExpression ex = new CarpetExpression(module, module.code(), cc.source(), cc.origin()); + final CarpetContext cc = (CarpetContext) c; + final CarpetExpression ex = new CarpetExpression(module, module.code(), cc.source(), cc.origin()); ex.getExpr().asATextSource(); ex.scriptRunCommand(this, cc.origin()); } @Override - public void delFunction(Module module, String funName) + public void delFunction(final Module module, final String funName) { super.delFunction(module, funName); // mcarpet if (funName.startsWith("__on_")) { // this is nasty, we have the host and function, yet we add it via names, but hey - works for now - String event = funName.replaceFirst("__on_",""); + final String event = funName.replaceFirst("__on_", ""); scriptServer().events.removeBuiltInEvent(event, this, funName); } } - public CarpetScriptHost retrieveForExecution(CommandSourceStack source, ServerPlayer player) + public CarpetScriptHost retrieveForExecution(final CommandSourceStack source, final ServerPlayer player) { CarpetScriptHost target = null; if (!perUser) @@ -615,96 +682,116 @@ public class CarpetScriptHost extends ScriptHost { target = (CarpetScriptHost) retrieveForExecution(player.getScoreboardName()); } - if (target != null && target.errorSnooper == null) target.setChatErrorSnooper(source); + if (target != null && target.errorSnooper == null) + { + target.setChatErrorSnooper(source); + } return target; } - public CarpetScriptHost retrieveOwnForExecution(CommandSourceStack source) throws CommandSyntaxException + public CarpetScriptHost retrieveOwnForExecution(final CommandSourceStack source) throws CommandSyntaxException { if (!perUser) { - if (errorSnooper == null) setChatErrorSnooper(source); + if (errorSnooper == null) + { + setChatErrorSnooper(source); + } return this; } // user based - ServerPlayer player; + final ServerPlayer player; try { player = source.getPlayerOrException(); } - catch (CommandSyntaxException ignored) + catch (final CommandSyntaxException ignored) { throw new SimpleCommandExceptionType(Component.literal("Cannot run player based apps without the player context")).create(); } - CarpetScriptHost userHost = (CarpetScriptHost)retrieveForExecution(player.getScoreboardName()); - if (userHost.errorSnooper == null) userHost.setChatErrorSnooper(source); + final CarpetScriptHost userHost = (CarpetScriptHost) retrieveForExecution(player.getScoreboardName()); + if (userHost.errorSnooper == null) + { + userHost.setChatErrorSnooper(source); + } return userHost; } - public Value handleCommandLegacy(CommandSourceStack source, String call, List coords, String arg) + public Value handleCommandLegacy(final CommandSourceStack source, final String call, final List coords, final String arg) { try { - CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); - Value res = callLegacy(source, call, coords, arg); + final CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); + final Value res = callLegacy(source, call, coords, arg); CarpetProfiler.end_current_section(currentSection); return res; } - catch (CarpetExpressionException exc) + catch (final CarpetExpressionException exc) { handleErrorWithStack("Error while running custom command", exc); } - catch (ArithmeticException ae) + catch (final ArithmeticException ae) { handleErrorWithStack("Math doesn't compute", ae); } - catch (StackOverflowError soe) + catch (final StackOverflowError soe) { handleErrorWithStack("Your thoughts are too deep", soe); } return Value.NULL; } - public Value handleCommand(CommandSourceStack source, FunctionValue function, List args) + public Value handleCommand(final CommandSourceStack source, final FunctionValue function, final List args) { try { return scriptServer().events.handleEvents.getWhileDisabled(() -> call(source, function, args)); } - catch (CarpetExpressionException exc) + catch (final CarpetExpressionException exc) { handleErrorWithStack("Error while running custom command", exc); } - catch (ArithmeticException ae) + catch (final ArithmeticException ae) { handleErrorWithStack("Math doesn't compute", ae); } - catch (StackOverflowError soe) + catch (final StackOverflowError soe) { handleErrorWithStack("Your thoughts are too deep", soe); } return Value.NULL; } - public Value callLegacy(CommandSourceStack source, String call, List coords, String arg) + public Value callLegacy(final CommandSourceStack source, final String call, final List coords, final String arg) { if (CarpetServer.scriptServer.stopAll) + { throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null); - FunctionValue function = getFunction(call); + } + final FunctionValue function = getFunction(call); if (function == null) + { throw new CarpetExpressionException("Couldn't find function '" + call + "' in app '" + this.getName() + "'", null); - List argv = new ArrayList<>(); + } + final List argv = new ArrayList<>(); if (coords != null) - for (Integer i: coords) - argv.add( (c, t) -> new NumericValue(i)); + { + for (final Integer i : coords) + { + argv.add((c, t) -> new NumericValue(i)); + } + } String sign = ""; - for (Tokenizer.Token tok : Tokenizer.simplepass(arg)) + for (final Tokenizer.Token tok : Tokenizer.simplepass(arg)) { switch (tok.type) { case VARIABLE: - LazyValue var = getGlobalVariable(tok.surface); - if (var != null) argv.add(var); + final LazyValue variable = getGlobalVariable(tok.surface); + if (variable != null) + { + argv.add(variable); + } break; case STRINGPARAM: argv.add((c, t) -> new StringValue(tok.surface)); @@ -714,31 +801,30 @@ public class CarpetScriptHost extends ScriptHost case LITERAL: try { - String finalSign = sign; - argv.add((c, t) ->new NumericValue(finalSign+tok.surface)); + final String finalSign = sign; + argv.add((c, t) -> new NumericValue(finalSign + tok.surface)); sign = ""; } - catch (NumberFormatException exception) + catch (final NumberFormatException exception) { - throw new CarpetExpressionException("Fail: "+sign+tok.surface+" seems like a number but it is" + + throw new CarpetExpressionException("Fail: " + sign + tok.surface + " seems like a number but it is" + " not a number. Use quotes to ensure its a string", null); } break; case HEX_LITERAL: try { - String finalSign = sign; - argv.add((c, t) -> new NumericValue(new BigInteger(finalSign+tok.surface.substring(2), 16).doubleValue())); + final String finalSign = sign; + argv.add((c, t) -> new NumericValue(new BigInteger(finalSign + tok.surface.substring(2), 16).doubleValue())); sign = ""; } - catch (NumberFormatException exception) + catch (final NumberFormatException exception) { - throw new CarpetExpressionException("Fail: "+sign+tok.surface+" seems like a number but it is" + + throw new CarpetExpressionException("Fail: " + sign + tok.surface + " seems like a number but it is" + " not a number. Use quotes to ensure its a string", null); } break; - case OPERATOR: - case UNARY_OPERATOR: + case OPERATOR, UNARY_OPERATOR: if ((tok.surface.equals("-") || tok.surface.equals("-u")) && sign.isEmpty()) { sign = "-"; @@ -750,22 +836,19 @@ public class CarpetScriptHost extends ScriptHost } break; case FUNCTION: - throw new CarpetExpressionException("Fail: passing functions like "+tok.surface+"() to invoke is " + + throw new CarpetExpressionException("Fail: passing functions like " + tok.surface + "() to invoke is " + "not allowed", null); - case OPEN_PAREN: - case COMMA: - case CLOSE_PAREN: - case MARKER: - throw new CarpetExpressionException("Fail: "+tok.surface+" is not allowed in invoke", null); + case OPEN_PAREN, COMMA, CLOSE_PAREN, MARKER: + throw new CarpetExpressionException("Fail: " + tok.surface + " is not allowed in invoke", null); } } - List args = function.getArguments(); + final List args = function.getArguments(); if (argv.size() != args.size()) { - String error = "Fail: stored function "+call+" takes "+args.size()+" arguments, not "+argv.size()+ ":\n"; + String error = "Fail: stored function " + call + " takes " + args.size() + " arguments, not " + argv.size() + ":\n"; for (int i = 0; i < max(argv.size(), args.size()); i++) { - error += (i "+(i " + (i < argv.size() ? argv.get(i).evalValue(null).getString() : "??") + "\n"; } throw new CarpetExpressionException(error, null); } @@ -773,97 +856,102 @@ public class CarpetScriptHost extends ScriptHost { // TODO: this is just for now - invoke would be able to invoke other hosts scripts assertAppIntegrity(function.getModule()); - Context context = new CarpetContext(this, source); + final Context context = new CarpetContext(this, source); return scriptServer().events.handleEvents.getWhileDisabled(() -> function.getExpression().evalValue( () -> function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv), context, Context.VOID )); } - catch (ExpressionException e) + catch (final ExpressionException e) { throw new CarpetExpressionException(e.getMessage(), e.stack); } } - public Value call(CommandSourceStack source, FunctionValue function, List argv) + public Value call(final CommandSourceStack source, final FunctionValue function, final List argv) { if (CarpetServer.scriptServer.stopAll) + { throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null); + } - List args = function.getArguments(); + final List args = function.getArguments(); if (argv.size() != args.size()) { - String error = "Fail: stored function "+function.getPrettyString()+" takes "+args.size()+" arguments, not "+argv.size()+ ":\n"; + String error = "Fail: stored function " + function.getPrettyString() + " takes " + args.size() + " arguments, not " + argv.size() + ":\n"; for (int i = 0; i < max(argv.size(), args.size()); i++) { - error += (i "+(i " + (i < argv.size() ? argv.get(i).getString() : "??") + "\n"; } throw new CarpetExpressionException(error, null); } try { assertAppIntegrity(function.getModule()); - Context context = new CarpetContext(this, source); + final Context context = new CarpetContext(this, source); return function.getExpression().evalValue( () -> function.execute(context, Context.VOID, function.getExpression(), function.getToken(), argv), context, Context.VOID ); } - catch (ExpressionException e) + catch (final ExpressionException e) { throw new CarpetExpressionException(e.getMessage(), e.stack); } } - public Value callUDF(CommandSourceStack source, FunctionValue fun, List argv) throws InvalidCallbackException, IntegrityException + public Value callUDF(final CommandSourceStack source, final FunctionValue fun, final List argv) throws InvalidCallbackException, IntegrityException { return callUDF(BlockPos.ZERO, source, fun, argv); } - public Value callUDF(BlockPos origin, CommandSourceStack source, FunctionValue fun, List argv) throws InvalidCallbackException, IntegrityException + public Value callUDF(final BlockPos origin, final CommandSourceStack source, final FunctionValue fun, final List argv) throws InvalidCallbackException, IntegrityException { if (CarpetServer.scriptServer.stopAll) + { return Value.NULL; - try { // cause we can't throw checked exceptions in lambda. Left if be until need to handle these more gracefully + } + try + { // cause we can't throw checked exceptions in lambda. Left if be until need to handle these more gracefully fun.assertArgsOk(argv, (b) -> { throw new InternalExpressionException(""); }); } - catch (InternalExpressionException ignored) + catch (final InternalExpressionException ignored) { throw new InvalidCallbackException(); } try { assertAppIntegrity(fun.getModule()); - Context context = new CarpetContext(this, source, origin); + final Context context = new CarpetContext(this, source, origin); return fun.getExpression().evalValue( () -> fun.execute(context, Context.VOID, fun.getExpression(), fun.getToken(), argv), context, Context.VOID); } - catch (ExpressionException e) + catch (final ExpressionException e) { handleExpressionException("Callback failed", e); } return Value.NULL; } - public Value callNow(FunctionValue fun, List arguments) + public Value callNow(final FunctionValue fun, final List arguments) { - ServerPlayer player = (user==null)?null:scriptServer().server.getPlayerList().getPlayerByName(user); - CommandSourceStack source = (player != null)?player.createCommandSourceStack():scriptServer().server.createCommandSourceStack(); - return scriptServer().events.handleEvents.getWhileDisabled(()->{ - try - { - return callUDF(source, fun, arguments); - } - catch (InvalidCallbackException ignored) - { - return Value.NULL; - } + final ServerPlayer player = (user == null) ? null : scriptServer().server.getPlayerList().getPlayerByName(user); + final CommandSourceStack source = (player != null) ? player.createCommandSourceStack() : scriptServer().server.createCommandSourceStack(); + return scriptServer().events.handleEvents.getWhileDisabled(() -> { + try + { + return callUDF(source, fun, arguments); + } + catch (final InvalidCallbackException ignored) + { + return Value.NULL; + } }); } @@ -872,26 +960,28 @@ public class CarpetScriptHost extends ScriptHost public void onClose() { super.onClose(); - FunctionValue closing = getFunction("__on_close"); + final FunctionValue closing = getFunction("__on_close"); if (closing != null && (parent != null || !isPerUser())) - // either global instance of a global task, or - // user host in player scoped app + // either global instance of a global task, or + // user host in player scoped app { callNow(closing, Collections.emptyList()); } if (user == null) { - String markerName = Auxiliary.MARKER_STRING + "_" + ((getName() == null) ? "" : getName()); - for (ServerLevel world : scriptServer().server.getAllLevels()) + final String markerName = Auxiliary.MARKER_STRING + "_" + ((getName() == null) ? "" : getName()); + for (final ServerLevel world : scriptServer().server.getAllLevels()) { - for (Entity e : world.getEntities(EntityType.ARMOR_STAND, (as) -> as.getTags().contains(markerName))) + for (final Entity e : world.getEntities(EntityType.ARMOR_STAND, (as) -> as.getTags().contains(markerName))) { e.discard(); } } if (this.saveTimeout > 0) + { dumpState(); + } } } @@ -905,26 +995,36 @@ public class CarpetScriptHost extends ScriptHost return Module.getData(main); } - public Tag readFileTag(FileArgument fdesc) + public Tag readFileTag(final FileArgument fdesc) { - if (getName() == null && !fdesc.isShared) return null; + if (getName() == null && !fdesc.isShared) + { + return null; + } if (fdesc.resource != null) + { return fdesc.getNbtData(main); + } if (parent == null) + { return globalState; - return ((CarpetScriptHost)parent).globalState; + } + return ((CarpetScriptHost) parent).globalState; } - public boolean writeTagFile(Tag tag, FileArgument fdesc) + public boolean writeTagFile(final Tag tag, final FileArgument fdesc) { - if (getName() == null && !fdesc.isShared) return false; // if belongs to an app, cannot be default host. + if (getName() == null && !fdesc.isShared) + { + return false; // if belongs to an app, cannot be default host. + } if (fdesc.resource != null) { return fdesc.saveNbtData(main, tag); } - CarpetScriptHost responsibleHost = (parent != null)?(CarpetScriptHost) parent:this; + final CarpetScriptHost responsibleHost = (parent != null) ? (CarpetScriptHost) parent : this; responsibleHost.globalState = tag; if (responsibleHost.saveTimeout == 0) { @@ -934,48 +1034,42 @@ public class CarpetScriptHost extends ScriptHost return true; } - public boolean removeResourceFile(FileArgument fdesc) + public boolean removeResourceFile(final FileArgument fdesc) { - if (getName() == null && !fdesc.isShared) return false; // - return fdesc.dropExistingFile(main); + return (getName() != null || fdesc.isShared) && fdesc.dropExistingFile(main); // } - public boolean appendLogFile(FileArgument fdesc, List data) + public boolean appendLogFile(final FileArgument fdesc, final List data) { - if (getName() == null && !fdesc.isShared) return false; // if belongs to an app, cannot be default host. - return fdesc.appendToTextFile(main, data); + return (getName() != null || fdesc.isShared) && fdesc.appendToTextFile(main, data); // if belongs to an app, cannot be default host. } - public List readTextResource(FileArgument fdesc) + public List readTextResource(final FileArgument fdesc) { - if (getName() == null && !fdesc.isShared) return null; - return fdesc.listFile(main); - } - - public JsonElement readJsonFile(FileArgument fdesc) - { - if (getName() == null && !fdesc.isShared) return null; - return fdesc.readJsonFile(main); + return getName() == null && !fdesc.isShared ? null : fdesc.listFile(main); } - public Stream listFolder(FileArgument fdesc) + public JsonElement readJsonFile(final FileArgument fdesc) { - if (getName() == null && !fdesc.isShared) return null; // - return fdesc.listFolder(main); + return getName() == null && !fdesc.isShared ? null : fdesc.readJsonFile(main); } - public boolean applyActionForResource(String path, boolean shared, Consumer action) + public Stream listFolder(final FileArgument fdesc) { - FileArgument fdesc = FileArgument.resourceFromPath(path, FileArgument.Reason.CREATE, shared); + return getName() == null && !fdesc.isShared ? null : fdesc.listFolder(main); + } + + public boolean applyActionForResource(final String path, final boolean shared, final Consumer action) + { + final FileArgument fdesc = FileArgument.resourceFromPath(path, FileArgument.Reason.CREATE, shared); return fdesc.findPathAndApply(main, action); } - public void tick() { if (this.saveTimeout > 0) { - this.saveTimeout --; + this.saveTimeout--; if (this.saveTimeout == 0) { dumpState(); @@ -983,7 +1077,7 @@ public class CarpetScriptHost extends ScriptHost } } - public void setChatErrorSnooper(CommandSourceStack source) + public void setChatErrorSnooper(final CommandSourceStack source) { responsibleSource = source; errorSnooper = (expr, /*Nullable*/ token, ctx, message) -> @@ -992,15 +1086,15 @@ public class CarpetScriptHost extends ScriptHost { source.getPlayerOrException(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { return null; } - String shebang = message+" in "+expr.getModuleName(); + String shebang = message + " in " + expr.getModuleName(); if (token != null) { - String[] lines = expr.getCodeString().split("\n"); + final String[] lines = expr.getCodeString().split("\n"); if (lines.length > 1) { @@ -1015,7 +1109,7 @@ public class CarpetScriptHost extends ScriptHost { Messenger.m(source, withLocals("l", lines[token.lineno - 1], ctx)); } - Messenger.m(source, withLocals("l", lines[token.lineno].substring(0, token.linepos), ctx), "r HERE>> ", + Messenger.m(source, withLocals("l", lines[token.lineno].substring(0, token.linepos), ctx), "r HERE>> ", withLocals("l", lines[token.lineno].substring(token.linepos), ctx)); if (lines.length > 1 && token.lineno < lines.length - 1) { @@ -1032,56 +1126,62 @@ public class CarpetScriptHost extends ScriptHost /** *

Creates a {@link Component} using {@link Messenger} that has the locals in the {@code line} snippet with a hover over - * tooltip with the value of the local at that location

- * @param line The line to find references to locals on + * tooltip with the value of the local at that location

+ * + * @param line The line to find references to locals on * @param context The {@link Context} to extract the locals from - * @param format The format to apply to each part of the line, without the trailing space + * @param format The format to apply to each part of the line, without the trailing space * @return A BaseText of the given line with the given format, that is visibly the same as passing those to Messenger, but with references to the - * locals in the {@link Context} with a hover over tooltip text + * locals in the {@link Context} with a hover over tooltip text * @implNote The implementation of this method is far from perfect, and won't detect actual references to variables, but try to find the strings - * and add the hover effect to anything that equals to any variable name, so short variable names may appear on random positions + * and add the hover effect to anything that equals to any variable name, so short variable names may appear on random positions */ - private static Component withLocals(String format, String line, Context context) + private static Component withLocals(String format, final String line, final Context context) { format += " "; - List stringsToFormat = new ArrayList<>(); - TreeMap posToLocal = new TreeMap<>(); //Holds whether a local variable name is found at a specific index - for (String local: context.variables.keySet()) + final List stringsToFormat = new ArrayList<>(); + final TreeMap posToLocal = new TreeMap<>(); //Holds whether a local variable name is found at a specific index + for (final String local : context.variables.keySet()) { int pos = line.indexOf(local); while (pos != -1) { posToLocal.merge(pos, local, (existingLocal, newLocal) -> { - if (newLocal.length() > existingLocal.length()) // Prefer longer variable names at the same position, since else single chars everywhere - return local; - else - return existingLocal; + // Prefer longer variable names at the same position, since else single chars everywhere + return newLocal.length() > existingLocal.length() ? local : existingLocal; }); pos = line.indexOf(local, pos + 1); } } int lastPos = 0; - for (Entry foundLocal : posToLocal.entrySet()) + for (final Entry foundLocal : posToLocal.entrySet()) { if (foundLocal.getKey() < lastPos) // system isn't perfect: part of another local + { continue; + } stringsToFormat.add(format + line.substring(lastPos, foundLocal.getKey())); stringsToFormat.add(format + foundLocal.getValue()); - Value val = context.variables.get(foundLocal.getValue()).evalValue(context); - String type = val.getTypeString(); + final Value val = context.variables.get(foundLocal.getValue()).evalValue(context); + final String type = val.getTypeString(); String value; - try { + try + { value = val.getPrettyString(); - } catch (StackOverflowError e) { + } + catch (final StackOverflowError e) + { value = "Exception while rendering variable, there seems to be a recursive reference in there"; } stringsToFormat.add("^ Value of '" + foundLocal.getValue() + "' at position (" + type + "): \n" - + value); + + value); lastPos = foundLocal.getKey() + foundLocal.getValue().length(); } if (line.length() != lastPos) - stringsToFormat.add(format + line.substring(lastPos, line.length())); + { + stringsToFormat.add(format + line.substring(lastPos)); + } return Messenger.c(stringsToFormat.toArray()); } @@ -1092,22 +1192,25 @@ public class CarpetScriptHost extends ScriptHost super.resetErrorSnooper(); } - public void handleErrorWithStack(String intro, Throwable exception) + public void handleErrorWithStack(final String intro, final Throwable exception) { if (responsibleSource != null) { - if (exception instanceof CarpetExpressionException) ((CarpetExpressionException) exception).printStack(responsibleSource); - String message = exception.getMessage(); - Messenger.m(responsibleSource, "r "+intro+( (message == null || message.isEmpty())?"":": "+message)); + if (exception instanceof final CarpetExpressionException cee) + { + cee.printStack(responsibleSource); + } + final String message = exception.getMessage(); + Messenger.m(responsibleSource, "r " + intro + ((message == null || message.isEmpty()) ? "" : ": " + message)); } else { - CarpetSettings.LOG.error(intro+": "+exception.getMessage()); + CarpetSettings.LOG.error(intro + ": " + exception.getMessage()); } } @Override - synchronized public void handleExpressionException(String message, ExpressionException exc) + public synchronized void handleExpressionException(final String message, final ExpressionException exc) { handleErrorWithStack(message, new CarpetExpressionException(exc.getMessage(), exc.stack)); } @@ -1120,19 +1223,19 @@ public class CarpetScriptHost extends ScriptHost { return scriptServer(); } - + @Override public CarpetScriptServer scriptServer() { - return (CarpetScriptServer)super.scriptServer(); + return (CarpetScriptServer) super.scriptServer(); } @Override - public boolean issueDeprecation(String feature) + public boolean issueDeprecation(final String feature) { - if(super.issueDeprecation(feature)) + if (super.issueDeprecation(feature)) { - Messenger.m(responsibleSource, "rb '"+feature+"' is deprecated and soon will be removed. Please consult the docs for their replacement"); + Messenger.m(responsibleSource, "rb '" + feature + "' is deprecated and soon will be removed. Please consult the docs for their replacement"); return true; } return false; diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 4ddf57a4..9ae29a2c 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -59,35 +59,38 @@ public class CarpetScriptServer extends ScriptServer //make static for now, but will change that later: public static final Logger LOG = LoggerFactory.getLogger("Scarpet"); public final MinecraftServer server; - public CarpetScriptHost globalHost; - public Map modules; - public Set unloadableModules; + public CarpetScriptHost globalHost; + public Map modules; + public Set unloadableModules; public long tickStart; public boolean stopAll; public int tickDepth; - private Set holyMoly; - public CarpetEventServer events; + private Set holyMoly; + public CarpetEventServer events; private static final List bundledModuleData = new ArrayList<>(); private static final List ruleModuleData = new ArrayList<>(); + /** * Registers a Scarpet App to be always available under the {@code /script load} list. - * @see Module#fromJarPath(String, String, boolean) - * + * * @param app The {@link Module} of the app + * @see Module#fromJarPath(String, String, boolean) */ - public static void registerBuiltInApp(Module app) { + public static void registerBuiltInApp(final Module app) + { bundledModuleData.add(app); } /** * Registers a Scarpet App to be used as a Rule App (to be controlled with the value of a Carpet rule). * Libraries should be registered with {@link #registerBuiltInScript(BundledModule)} instead - * @see Module#fromJarPath(String, String, boolean) - * + * * @param app The {@link Module} of the app. + * @see Module#fromJarPath(String, String, boolean) */ - public static void registerSettingsApp(Module app) { + public static void registerSettingsApp(final Module app) + { ruleModuleData.add(app); } @@ -105,7 +108,7 @@ public class CarpetScriptServer extends ScriptServer registerBuiltInApp(Module.carpetNative("distance_beta", false)); } - public CarpetScriptServer(MinecraftServer server) + public CarpetScriptServer(final MinecraftServer server) { this.server = server; init(); @@ -126,13 +129,14 @@ public class CarpetScriptServer extends ScriptServer { CarpetServer.settingsManager.initializeScarpetRules(); CarpetServer.extensions.forEach(e -> { - if (e.extensionSettingsManager() != null) { + if (e.extensionSettingsManager() != null) + { e.extensionSettingsManager().initializeScarpetRules(); } }); if (CarpetSettings.scriptsAutoload) { - for (String moduleName: listAvailableModules(false)) + for (final String moduleName : listAvailableModules(false)) { addScriptHost(server.createCommandSourceStack(), moduleName, null, true, true, false, null); } @@ -140,40 +144,53 @@ public class CarpetScriptServer extends ScriptServer CarpetEventServer.Event.START.onTick(); } - public Module getModule(String name, boolean allowLibraries) + public Module getModule(final String name, final boolean allowLibraries) { - try { - Path folder = server.getWorldPath(LevelResource.ROOT).resolve("scripts"); - if (!Files.exists(folder)) + try + { + final Path folder = server.getWorldPath(LevelResource.ROOT).resolve("scripts"); + if (!Files.exists(folder)) + { Files.createDirectories(folder); - try (Stream folderLister = Files.list(folder)) { - Optional scriptPath = folderLister - .filter(script -> - script.getFileName().toString().equalsIgnoreCase(name + ".sc") || - (allowLibraries && script.getFileName().toString().equalsIgnoreCase(name+".scl")) - ).findFirst(); + } + try (final Stream folderLister = Files.list(folder)) + { + final Optional scriptPath = folderLister + .filter(script -> + script.getFileName().toString().equalsIgnoreCase(name + ".sc") || + (allowLibraries && script.getFileName().toString().equalsIgnoreCase(name + ".scl")) + ).findFirst(); if (scriptPath.isPresent()) + { return Module.fromPath(scriptPath.get()); + } } if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { - Path globalFolder = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts"); - if (!Files.exists(globalFolder)) + final Path globalFolder = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts"); + if (!Files.exists(globalFolder)) + { Files.createDirectories(globalFolder); - try (Stream folderWalker = Files.walk(globalFolder)) { - Optional scriptPath = folderWalker + } + try (final Stream folderWalker = Files.walk(globalFolder)) + { + final Optional scriptPath = folderWalker .filter(script -> script.getFileName().toString().equalsIgnoreCase(name + ".sc") || (allowLibraries && script.getFileName().toString().equalsIgnoreCase(name + ".scl"))) .findFirst(); if (scriptPath.isPresent()) + { return Module.fromPath(scriptPath.get()); + } } } - } catch (IOException e) { + } + catch (final IOException e) + { CarpetSettings.LOG.error("Exception while loading the app: ", e); } - for (Module moduleData : bundledModuleData) + for (final Module moduleData : bundledModuleData) { if (moduleData.name().equalsIgnoreCase(name) && (allowLibraries || !moduleData.library())) { @@ -182,10 +199,10 @@ public class CarpetScriptServer extends ScriptServer } return null; } - - public Module getRuleModule(String name) + + public Module getRuleModule(final String name) { - for (Module moduleData : ruleModuleData) + for (final Module moduleData : ruleModuleData) { if (moduleData.name().equalsIgnoreCase(name)) { @@ -195,101 +212,116 @@ public class CarpetScriptServer extends ScriptServer return null; } - public List listAvailableModules(boolean includeBuiltIns) + public List listAvailableModules(final boolean includeBuiltIns) { - List moduleNames = new ArrayList<>(); + final List moduleNames = new ArrayList<>(); if (includeBuiltIns) { - for (Module mi : bundledModuleData) + for (final Module mi : bundledModuleData) { - if (!mi.library() && !mi.name().endsWith("_beta")) moduleNames.add(mi.name()); + if (!mi.library() && !mi.name().endsWith("_beta")) + { + moduleNames.add(mi.name()); + } } } - try { - Path worldScripts = server.getWorldPath(LevelResource.ROOT).resolve("scripts"); - if (!Files.exists(worldScripts)) + try + { + final Path worldScripts = server.getWorldPath(LevelResource.ROOT).resolve("scripts"); + if (!Files.exists(worldScripts)) + { Files.createDirectories(worldScripts); - try (Stream folderLister = Files.list(worldScripts)) { + } + try (final Stream folderLister = Files.list(worldScripts)) + { folderLister - .filter(f -> f.toString().endsWith(".sc")) - .forEach(f -> moduleNames.add(f.getFileName().toString().replaceFirst("\\.sc$","").toLowerCase(Locale.ROOT))); + .filter(f -> f.toString().endsWith(".sc")) + .forEach(f -> moduleNames.add(f.getFileName().toString().replaceFirst("\\.sc$", "").toLowerCase(Locale.ROOT))); } if (includeBuiltIns && (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT)) { - Path globalScripts = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts"); + final Path globalScripts = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts"); if (!Files.exists(globalScripts)) + { Files.createDirectories(globalScripts); - try (Stream folderWalker = Files.walk(globalScripts, FileVisitOption.FOLLOW_LINKS)) { + } + try (final Stream folderWalker = Files.walk(globalScripts, FileVisitOption.FOLLOW_LINKS)) + { folderWalker - .filter(f -> f.toString().endsWith(".sc")) - .forEach(f -> moduleNames.add(f.getFileName().toString().replaceFirst("\\.sc$","").toLowerCase(Locale.ROOT))); + .filter(f -> f.toString().endsWith(".sc")) + .forEach(f -> moduleNames.add(f.getFileName().toString().replaceFirst("\\.sc$", "").toLowerCase(Locale.ROOT))); } } - } catch (IOException e) { + } + catch (final IOException e) + { CarpetSettings.LOG.error("Exception while searching for apps: ", e); } return moduleNames; } - public CarpetScriptHost getAppHostByName(String name) + public CarpetScriptHost getAppHostByName(final String name) { - if (name == null) - return globalHost; - return modules.get(name); + return name == null ? globalHost : modules.get(name); } - public boolean addScriptHost(CommandSourceStack source, String name, Predicate commandValidator, - boolean perPlayer, boolean autoload, boolean isRuleApp, AppStoreManager.StoreNode installer) + public boolean addScriptHost(final CommandSourceStack source, String name, Predicate commandValidator, + final boolean perPlayer, final boolean autoload, final boolean isRuleApp, final AppStoreManager.StoreNode installer) { - CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet load", CarpetProfiler.TYPE.GENERAL); - if (commandValidator == null) commandValidator = p -> true; - long start = System.nanoTime(); + final CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet load", CarpetProfiler.TYPE.GENERAL); + if (commandValidator == null) + { + commandValidator = p -> true; + } + final long start = System.nanoTime(); name = name.toLowerCase(Locale.ROOT); boolean reload = false; if (modules.containsKey(name)) { - if (isRuleApp) return false; + if (isRuleApp) + { + return false; + } removeScriptHost(source, name, false, isRuleApp); reload = true; } - Module module = isRuleApp ? getRuleModule(name) : getModule(name, false); + final Module module = isRuleApp ? getRuleModule(name) : getModule(name, false); if (module == null) { - Messenger.m(source, "r Failed to add "+name+" app: App not found"); + Messenger.m(source, "r Failed to add " + name + " app: App not found"); return false; } - CarpetScriptHost newHost; + final CarpetScriptHost newHost; try { newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp, installer); } - catch (LoadException e) + catch (final LoadException e) { Messenger.m(source, "r Failed to add " + name + " app" + (e.getMessage() == null ? "" : ": " + e.getMessage())); return false; } - // config needs to be read as we load the app since some events use that info - //if (!newHost.readConfig()) - //{ - // Messenger.m(source, "r Failed to add "+name+" app: invalid app config (via '__config()' function)"); - // return false; - //} modules.put(name, newHost); - if (!isRuleApp) unloadableModules.add(name); + if (!isRuleApp) + { + unloadableModules.add(name); + } if (autoload && !newHost.persistenceRequired) { removeScriptHost(source, name, false, false); return false; } - //addEvents(source, name); - String action = (installer!=null)?(reload?"reinstalled":"installed"):(reload?"reloaded":"loaded"); + final String action = (installer != null) ? (reload ? "reinstalled" : "installed") : (reload ? "reloaded" : "loaded"); - String finalName = name; - Boolean isCommandAdded = newHost.addAppCommands(s -> { - if (!isRuleApp) Messenger.m(source, Messenger.c("r Failed to add app '" + finalName + "': ", s)); + final String finalName = name; + final Boolean isCommandAdded = newHost.addAppCommands(s -> { + if (!isRuleApp) + { + Messenger.m(source, Messenger.c("r Failed to add app '" + finalName + "': ", s)); + } }); if (isCommandAdded == null) // error should be dispatched { @@ -299,17 +331,23 @@ public class CarpetScriptServer extends ScriptServer else if (isCommandAdded) { CommandHelper.notifyPlayersCommandsChanged(server); - if (!isRuleApp) Messenger.m(source, "gi "+name+" app "+action+" with /"+name+" command"); + if (!isRuleApp) + { + Messenger.m(source, "gi " + name + " app " + action + " with /" + name + " command"); + } } else { - if (!isRuleApp) Messenger.m(source, "gi "+name+" app "+action); + if (!isRuleApp) + { + Messenger.m(source, "gi " + name + " app " + action); + } } if (newHost.isPerUser()) { // that will provide player hosts right at the startup - for (ServerPlayer player : source.getServer().getPlayerList().getPlayers()) + for (final ServerPlayer player : source.getServer().getPlayerList().getPlayers()) { newHost.retrieveForExecution(player.createCommandSourceStack(), player); } @@ -317,59 +355,76 @@ public class CarpetScriptServer extends ScriptServer else { // global app - calling start now. - FunctionValue onStart = newHost.getFunction("__on_start"); - if (onStart != null) newHost.callNow(onStart, Collections.emptyList()); + final FunctionValue onStart = newHost.getFunction("__on_start"); + if (onStart != null) + { + newHost.callNow(onStart, Collections.emptyList()); + } } CarpetProfiler.end_current_section(currentSection); - long end = System.nanoTime(); - CarpetSettings.LOG.info("App "+name+" loaded in "+(end-start)/1000000+" ms"); + final long end = System.nanoTime(); + CarpetSettings.LOG.info("App " + name + " loaded in " + (end - start) / 1000000 + " ms"); return true; } - public boolean isInvalidCommandRoot(String appName) + public boolean isInvalidCommandRoot(final String appName) { return holyMoly.contains(appName); } - public boolean removeScriptHost(CommandSourceStack source, String name, boolean notifySource, boolean isRuleApp) + public boolean removeScriptHost(final CommandSourceStack source, String name, final boolean notifySource, final boolean isRuleApp) { name = name.toLowerCase(Locale.ROOT); if (!modules.containsKey(name) || (!isRuleApp && !unloadableModules.contains(name))) { - if (notifySource) Messenger.m(source, "r No such app found: ", "wb " + name); + if (notifySource) + { + Messenger.m(source, "r No such app found: ", "wb " + name); + } return false; } // stop all events associated with name - CarpetScriptHost host = modules.remove(name); + final CarpetScriptHost host = modules.remove(name); events.removeAllHostEvents(host); host.onClose(); if (host.hasCommand) - ((CommandDispatcherInterface)server.getCommands().getDispatcher()).carpet$unregister(name); - if (!isRuleApp) unloadableModules.remove(name); + { + ((CommandDispatcherInterface) server.getCommands().getDispatcher()).carpet$unregister(name); + } + if (!isRuleApp) + { + unloadableModules.remove(name); + } CommandHelper.notifyPlayersCommandsChanged(server); - if (notifySource) Messenger.m(source, "gi Removed "+name+" app"); + if (notifySource) + { + Messenger.m(source, "gi Removed " + name + " app"); + } return true; } - public boolean uninstallApp(CommandSourceStack source, String name) + public boolean uninstallApp(final CommandSourceStack source, String name) { try { name = name.toLowerCase(Locale.ROOT); - Path folder = server.getWorldPath(LevelResource.ROOT).resolve("scripts/trash"); - if (!Files.exists(folder)) Files.createDirectories(folder); - if (!Files.exists(folder.getParent().resolve(name+".sc"))) + final Path folder = server.getWorldPath(LevelResource.ROOT).resolve("scripts/trash"); + if (!Files.exists(folder)) + { + Files.createDirectories(folder); + } + if (!Files.exists(folder.getParent().resolve(name + ".sc"))) { Messenger.m(source, "App doesn't exist in the world scripts folder, so can only be unloaded"); return false; } removeScriptHost(source, name, false, false); - Files.move(folder.getParent().resolve(name+".sc"), folder.resolve(name+".sc"), StandardCopyOption.REPLACE_EXISTING); - Messenger.m(source, "gi Removed "+name+" app"); + Files.move(folder.getParent().resolve(name + ".sc"), folder.resolve(name + ".sc"), StandardCopyOption.REPLACE_EXISTING); + Messenger.m(source, "gi Removed " + name + " app"); return true; } - catch (IOException exc) + catch (final IOException exc) { Messenger.m(source, "rb Failed to uninstall the app"); } @@ -380,10 +435,13 @@ public class CarpetScriptServer extends ScriptServer { CarpetProfiler.ProfilerToken token; token = CarpetProfiler.start_section(null, "Scarpet schedule", CarpetProfiler.TYPE.GENERAL); - events.handleEvents.getWhileDisabled( () -> {events.tick(); return null;}); + events.handleEvents.getWhileDisabled(() -> { + events.tick(); + return null; + }); CarpetProfiler.end_current_section(token); token = CarpetProfiler.start_section(null, "Scarpet app data", CarpetProfiler.TYPE.GENERAL); - for (CarpetScriptHost host : modules.values()) + for (final CarpetScriptHost host : modules.values()) { host.tick(); } @@ -393,14 +451,14 @@ public class CarpetScriptServer extends ScriptServer public void onClose() { CarpetEventServer.Event.SHUTDOWN.onTick(); - for (CarpetScriptHost host : modules.values()) + for (final CarpetScriptHost host : modules.values()) { host.onClose(); events.removeAllHostEvents(host); } } - public void onPlayerJoin(ServerPlayer player) + public void onPlayerJoin(final ServerPlayer player) { modules.values().forEach(h -> { @@ -410,36 +468,38 @@ public class CarpetScriptServer extends ScriptServer { h.retrieveOwnForExecution(player.createCommandSourceStack()); } - catch (CommandSyntaxException ignored) + catch (final CommandSyntaxException ignored) { } } }); } - private static record TransferData(boolean perUser, Predicate commandValidator, boolean isRuleApp) + private record TransferData(boolean perUser, Predicate commandValidator, + boolean isRuleApp) { - private TransferData(CarpetScriptHost host) + private TransferData(final CarpetScriptHost host) { this(host.perUser, host.commandValidator, host.isRuleApp); } } - public void reload(MinecraftServer server) + public void reload(final MinecraftServer server) { - Map apps = new HashMap<>(); + final Map apps = new HashMap<>(); modules.forEach((s, h) -> apps.put(s, new TransferData(h))); apps.keySet().forEach(s -> removeScriptHost(server.createCommandSourceStack(), s, false, false)); CarpetEventServer.Event.clearAllBuiltinEvents(); init(); - apps.forEach((s, data) -> addScriptHost(server.createCommandSourceStack(), s,data.commandValidator, data.perUser,false, data.isRuleApp, null)); + apps.forEach((s, data) -> addScriptHost(server.createCommandSourceStack(), s, data.commandValidator, data.perUser, false, data.isRuleApp, null)); } public void reAddCommands() { - modules.values().forEach(host -> host.addAppCommands(s -> {})); + modules.values().forEach(host -> host.addAppCommands(s -> { + })); } - + public static void parseFunctionClasses() { ExpressionException.prepareForDoom(); // see fc-#1172 @@ -451,7 +511,7 @@ public class CarpetScriptServer extends ScriptServer AnnotationParser.parseFunctionClass(Loops.class); AnnotationParser.parseFunctionClass(Sys.class); AnnotationParser.parseFunctionClass(Threading.class); - + // API AnnotationParser.parseFunctionClass(Auxiliary.class); AnnotationParser.parseFunctionClass(BlockIterators.class); diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index 748da050..430159ca 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -13,6 +13,7 @@ public class Context { NONE, VOID, BOOLEAN, NUMBER, STRING, LIST, ITERATOR, SIGNATURE, LOCALIZATION, LVALUE, MAPDEF } + public static final Type NONE = Type.NONE; public static final Type VOID = Type.VOID; public static final Type BOOLEAN = Type.BOOLEAN; @@ -29,32 +30,32 @@ public class Context public final ScriptHost host; - public Context(ScriptHost host) + public Context(final ScriptHost host) { this.host = host; } - public LazyValue getVariable(String name) + public LazyValue getVariable(final String name) { return variables.get(name); } - public void setVariable(String name, LazyValue lv) + public void setVariable(final String name, final LazyValue lv) { variables.put(name, lv); } - public void delVariable(String variable) + public void delVariable(final String variable) { variables.remove(variable); } - public void removeVariablesMatching(String varname) + public void removeVariablesMatching(final String varname) { variables.entrySet().removeIf(e -> e.getKey().startsWith(varname)); } - public Context with(String variable, LazyValue lv) + public Context with(final String variable, final LazyValue lv) { variables.put(variable, lv); return this; @@ -67,7 +68,7 @@ public class Context public Context recreate() { - Context ctx = duplicate(); + final Context ctx = duplicate(); ctx.initialize(); return ctx; } @@ -84,12 +85,12 @@ public class Context { return new Context(this.host); } + public ScriptHost.ErrorSnooper getErrorSnooper() { return host.errorSnooper; } - /** * immutable context only for reason on reporting access violations in evaluating expressions in optimizization * mode detecting any potential violations that may happen on the way @@ -97,10 +98,11 @@ public class Context public static class ContextForErrorReporting extends Context { public ScriptHost.ErrorSnooper optmizerEerrorSnooper; - public ContextForErrorReporting(Context parent) + + public ContextForErrorReporting(final Context parent) { super(null); - optmizerEerrorSnooper = parent.host.errorSnooper; + optmizerEerrorSnooper = parent.host.errorSnooper; } @Override @@ -116,31 +118,64 @@ public class Context "of scarpet authors. Please report this issue directly to the scarpet issue tracker"); } - @Override - public LazyValue getVariable(String name) { badProgrammer(); return null;} @Override - public void setVariable(String name, LazyValue lv) { badProgrammer(); } + public LazyValue getVariable(final String name) + { + badProgrammer(); + return null; + } @Override - public void delVariable(String variable) { badProgrammer(); } + public void setVariable(final String name, final LazyValue lv) + { + badProgrammer(); + } @Override - public void removeVariablesMatching(String varname) { badProgrammer(); } + public void delVariable(final String variable) + { + badProgrammer(); + } @Override - public Context with(String variable, LazyValue lv) { badProgrammer(); return this; } + public void removeVariablesMatching(final String varname) + { + badProgrammer(); + } @Override - public Set getAllVariableNames() { badProgrammer(); return null;} + public Context with(final String variable, final LazyValue lv) + { + badProgrammer(); + return this; + } @Override - public Context recreate() { badProgrammer(); return null;} + public Set getAllVariableNames() + { + badProgrammer(); + return null; + } @Override - protected void initialize() { badProgrammer();} + public Context recreate() + { + badProgrammer(); + return null; + } @Override - public Context duplicate() { badProgrammer(); return null;} + protected void initialize() + { + badProgrammer(); + } + + @Override + public Context duplicate() + { + badProgrammer(); + return null; + } } } diff --git a/src/main/java/carpet/script/EntityEventsGroup.java b/src/main/java/carpet/script/EntityEventsGroup.java index a249f67c..41b1dc3e 100644 --- a/src/main/java/carpet/script/EntityEventsGroup.java +++ b/src/main/java/carpet/script/EntityEventsGroup.java @@ -8,72 +8,93 @@ import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; import carpet.script.value.ValueConversions; + import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; + import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; public class EntityEventsGroup { - private static record EventKey(String host, String user) {} + private record EventKey(String host, String user) + { + } + private final Map> actions; private final Entity entity; - public EntityEventsGroup(Entity e) + + public EntityEventsGroup(final Entity e) { actions = new HashMap<>(); entity = e; } - public void onEvent(Event type, Object... args) + public void onEvent(final Event type, final Object... args) { - if (actions.isEmpty()) return; // most of the cases, trying to be nice - Map actionSet = actions.get(type); - if (actionSet == null) return; - if (CarpetServer.scriptServer == null) return; // executed after world is closin down - for (Iterator> iterator = actionSet.entrySet().iterator(); iterator.hasNext(); ) + if (actions.isEmpty()) { - Map.Entry action = iterator.next(); - EventKey key = action.getKey(); - ScriptHost host = CarpetServer.scriptServer.getAppHostByName(key.host()); + return; // most of the cases, trying to be nice + } + final Map actionSet = actions.get(type); + if (actionSet == null) + { + return; + } + if (CarpetServer.scriptServer == null) + { + return; // executed after world is closin down + } + for (final Iterator> iterator = actionSet.entrySet().iterator(); iterator.hasNext(); ) + { + final Map.Entry action = iterator.next(); + final EventKey key = action.getKey(); + final ScriptHost host = CarpetServer.scriptServer.getAppHostByName(key.host()); if (host == null) { iterator.remove(); continue; } - if (key.user() != null) + if (key.user() != null && entity.getServer().getPlayerList().getPlayerByName(key.user()) == null) { - if (entity.getServer().getPlayerList().getPlayerByName(key.user())==null) - { - iterator.remove(); - continue; - } + iterator.remove(); + continue; } if (type.call(action.getValue(), entity, args) == CarpetEventServer.CallbackResult.FAIL) + { iterator.remove(); + } + } + if (actionSet.isEmpty()) + { + actions.remove(type); } - if (actionSet.isEmpty()) actions.remove(type); } - public void addEvent(Event type, ScriptHost host, FunctionValue fun, List extraargs) + public void addEvent(final Event type, final ScriptHost host, final FunctionValue fun, final List extraargs) { - EventKey key = new EventKey(host.getName(), host.user); + final EventKey key = new EventKey(host.getName(), host.user); if (fun != null) { - CarpetEventServer.Callback call = type.create(key, fun, extraargs); + final CarpetEventServer.Callback call = type.create(key, fun, extraargs); if (call == null) - throw new InternalExpressionException("wrong number of arguments for callback, required "+type.argcount); + { + throw new InternalExpressionException("wrong number of arguments for callback, required " + type.argcount); + } actions.computeIfAbsent(type, k -> new HashMap<>()).put(key, call); } else { actions.computeIfAbsent(type, k -> new HashMap<>()).remove(key); if (actions.get(type).isEmpty()) + { actions.remove(type); + } } } @@ -84,11 +105,11 @@ public class EntityEventsGroup public static final Event ON_DEATH = new Event("on_death", 1) { @Override - public List makeArgs(Entity entity, Object... providedArgs) + public List makeArgs(final Entity entity, final Object... providedArgs) { return Arrays.asList( new EntityValue(entity), - new StringValue((String)providedArgs[0]) + new StringValue((String) providedArgs[0]) ); } }; @@ -97,22 +118,22 @@ public class EntityEventsGroup public static final Event ON_DAMAGE = new Event("on_damaged", 3) { @Override - public List makeArgs(Entity entity, Object... providedArgs) + public List makeArgs(final Entity entity, final Object... providedArgs) { - float amount = (Float)providedArgs[0]; - DamageSource source = (DamageSource)providedArgs[1]; + final float amount = (Float) providedArgs[0]; + final DamageSource source = (DamageSource) providedArgs[1]; return Arrays.asList( new EntityValue(entity), new NumericValue(amount), new StringValue(source.getMsgId()), - source.getEntity()==null?Value.NULL:new EntityValue(source.getEntity()) + source.getEntity() == null ? Value.NULL : new EntityValue(source.getEntity()) ); } }; public static final Event ON_MOVE = new Event("on_move", 3) { @Override - public List makeArgs(Entity entity, Object... providedArgs) + public List makeArgs(final Entity entity, final Object... providedArgs) { return Arrays.asList( new EntityValue(entity), @@ -125,26 +146,30 @@ public class EntityEventsGroup public final int argcount; public final String id; - public Event(String identifier, int args) + + public Event(final String identifier, final int args) { id = identifier; - argcount = args+1; // entity is not extra + argcount = args + 1; // entity is not extra byName.put(identifier, this); } - public CarpetEventServer.Callback create(EventKey key, FunctionValue function, List extraArgs) + + public CarpetEventServer.Callback create(final EventKey key, final FunctionValue function, final List extraArgs) { - if ((function.getArguments().size()-(extraArgs == null ? 0 : extraArgs.size())) != argcount) + if ((function.getArguments().size() - (extraArgs == null ? 0 : extraArgs.size())) != argcount) { return null; } return new CarpetEventServer.Callback(key.host(), key.user(), function, extraArgs); } - public CarpetEventServer.CallbackResult call(CarpetEventServer.Callback tickCall, Entity entity, Object ... args) + + public CarpetEventServer.CallbackResult call(final CarpetEventServer.Callback tickCall, final Entity entity, final Object... args) { - assert args.length == argcount-1; + assert args.length == argcount - 1; return tickCall.execute(entity.createCommandSourceStack(), makeArgs(entity, args)); } - protected List makeArgs(Entity entity, Object ... args) + + protected List makeArgs(final Entity entity, final Object... args) { return Collections.singletonList(new EntityValue(entity)); } diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 90f493c2..c9aca6af 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -44,9 +44,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; +import java.util.function.*; import java.util.stream.Collectors; import static java.lang.Math.max; @@ -54,9 +52,15 @@ import static java.lang.Math.min; public class Expression { - /** The current infix expression */ + /** + * The current infix expression + */ private String expression; - String getCodeString() {return expression;} + + String getCodeString() + { + return expression; + } private boolean allowNewlineSubstitutions = true; private boolean allowComments = false; @@ -74,23 +78,36 @@ public class Expression allowComments = true; } - public void asAModule(Module mi) + public void asAModule(final Module mi) { module = mi; } - /** Cached AST (Abstract Syntax Tree) (root) of the expression */ + /** + * Cached AST (Abstract Syntax Tree) (root) of the expression + */ private LazyValue ast = null; - /** script specific operatos and built-in functions */ + /** + * script specific operatos and built-in functions + */ private final Map operators = new Object2ObjectOpenHashMap<>(); - public boolean isAnOperator(String opname) { return operators.containsKey(opname) || operators.containsKey(opname+"u");} - private final Map functions = new Object2ObjectOpenHashMap<>(); - public Set getFunctionNames() {return functions.keySet();} + public boolean isAnOperator(final String opname) + { + return operators.containsKey(opname) || operators.containsKey(opname + "u"); + } + + private final Map functions = new Object2ObjectOpenHashMap<>(); + + public Set getFunctionNames() + { + return functions.keySet(); + } private final Map functionalEquivalence = new Object2ObjectOpenHashMap<>(); - public void addFunctionalEquivalence(String operator, String function) + + public void addFunctionalEquivalence(final String operator, final String function) { assert operators.containsKey(operator); assert functions.containsKey(function); @@ -105,27 +122,30 @@ public class Expression "false", Value.FALSE ); - protected Value getConstantFor(String surface) + protected Value getConstantFor(final String surface) { return constants.get(surface); } - public List getExpressionSnippet(Tokenizer.Token token) + public List getExpressionSnippet(final Tokenizer.Token token) { - String code = this.getCodeString(); - List output = new ArrayList<>(getExpressionSnippetLeftContext(token, code, 1)); - List context = getExpressionSnippetContext(token, code); - output.add(context.get(0)+" HERE>> "+context.get(1)); + final String code = this.getCodeString(); + final List output = new ArrayList<>(getExpressionSnippetLeftContext(token, code, 1)); + final List context = getExpressionSnippetContext(token, code); + output.add(context.get(0) + " HERE>> " + context.get(1)); output.addAll(getExpressionSnippetRightContext(token, code, 1)); return output; } - private static List getExpressionSnippetLeftContext(Tokenizer.Token token, String expr, int contextsize) + private static List getExpressionSnippetLeftContext(final Tokenizer.Token token, final String expr, final int contextsize) { - List output = new ArrayList<>(); - String[] lines = expr.split("\n"); - if (lines.length == 1) return output; - for (int lno=token.lineno-1; lno >=0 && output.size() < contextsize; lno-- ) + final List output = new ArrayList<>(); + final String[] lines = expr.split("\n"); + if (lines.length == 1) + { + return output; + } + for (int lno = token.lineno - 1; lno >= 0 && output.size() < contextsize; lno--) { output.add(lines[lno]); } @@ -133,10 +153,10 @@ public class Expression return output; } - private static List getExpressionSnippetContext(Tokenizer.Token token, String expr) + private static List getExpressionSnippetContext(final Tokenizer.Token token, final String expr) { - List output = new ArrayList<>(); - String[] lines = expr.split("\n"); + final List output = new ArrayList<>(); + final String[] lines = expr.split("\n"); if (lines.length > 1) { output.add(lines[token.lineno].substring(0, token.linepos)); @@ -144,18 +164,21 @@ public class Expression } else { - output.add( expr.substring(max(0, token.pos-40), token.pos)); - output.add( expr.substring(token.pos, min(token.pos+1+40, expr.length()))); + output.add(expr.substring(max(0, token.pos - 40), token.pos)); + output.add(expr.substring(token.pos, min(token.pos + 1 + 40, expr.length()))); } return output; } - private static List getExpressionSnippetRightContext(Tokenizer.Token token, String expr, int contextsize) + private static List getExpressionSnippetRightContext(final Tokenizer.Token token, final String expr, final int contextsize) { - List output = new ArrayList<>(); - String[] lines = expr.split("\n"); - if (lines.length == 1) { return output; } - for (int lno=token.lineno+1; lno < lines.length && output.size() < contextsize; lno++ ) + final List output = new ArrayList<>(); + final String[] lines = expr.split("\n"); + if (lines.length == 1) + { + return output; + } + for (int lno = token.lineno + 1; lno < lines.length && output.size() < contextsize; lno++) { output.add(lines[lno]); } @@ -163,34 +186,37 @@ public class Expression } - public void addLazyUnaryOperator(String surface, int precedence, boolean leftAssoc, boolean pure, Function staticTyper, - TriFunction lazyfun) + public void addLazyUnaryOperator(final String surface, final int precedence, final boolean leftAssoc, final boolean pure, final Function staticTyper, + final TriFunction lazyfun) { - operators.put(surface+"u", new AbstractLazyOperator(precedence, leftAssoc) + operators.put(surface + "u", new AbstractLazyOperator(precedence, leftAssoc) { @Override - public boolean pure() { + public boolean pure() + { return pure; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public Context.Type staticType(Context.Type outerType) { + public Context.Type staticType(final Context.Type outerType) + { return staticTyper.apply(outerType); } @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression e, Tokenizer.Token token, LazyValue v, LazyValue v2) + public LazyValue lazyEval(final Context c, final Context.Type t, final Expression e, final Tokenizer.Token token, final LazyValue v, final LazyValue v2) { try { return lazyfun.apply(c, t, v); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, token); } @@ -199,29 +225,31 @@ public class Expression } - public void addLazyBinaryOperatorWithDelegation(String surface, int precedence, boolean leftAssoc, boolean pure, - SexFunction lazyfun) + public void addLazyBinaryOperatorWithDelegation(final String surface, final int precedence, final boolean leftAssoc, final boolean pure, + final SexFunction lazyfun) { operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) { @Override - public boolean pure() { + public boolean pure() + { return pure; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(final Context c, final Context.Type type, final Expression e, final Tokenizer.Token t, final LazyValue v1, final LazyValue v2) { try { return lazyfun.apply(c, type, e, t, v1, v2); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -229,35 +257,37 @@ public class Expression }); } - public void addCustomFunction(String name, ILazyFunction fun) + public void addCustomFunction(final String name, final ILazyFunction fun) { functions.put(name, fun); } - public void addLazyFunctionWithDelegation(String name, int numpar, boolean pure, boolean transitive, - QuinnFunction, LazyValue> lazyfun) + public void addLazyFunctionWithDelegation(final String name, final int numpar, final boolean pure, final boolean transitive, + final QuinnFunction, LazyValue> lazyfun) { functions.put(name, new AbstractLazyFunction(numpar, name) { @Override - public boolean pure() { + public boolean pure() + { return pure; } @Override - public boolean transitive() { + public boolean transitive() + { return transitive; } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List lv) + public LazyValue lazyEval(final Context c, final Context.Type type, final Expression e, final Tokenizer.Token t, final List lv) { ILazyFunction.checkInterrupts(); try { return lazyfun.apply(c, type, e, t, lv); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -265,30 +295,32 @@ public class Expression }); } - public void addFunctionWithDelegation(String name, int numpar, boolean pure, boolean transitive, - QuinnFunction, Value> fun) + public void addFunctionWithDelegation(final String name, final int numpar, final boolean pure, final boolean transitive, + final QuinnFunction, Value> fun) { functions.put(name, new AbstractLazyFunction(numpar, name) { @Override - public boolean pure() { + public boolean pure() + { return pure; } @Override - public boolean transitive() { + public boolean transitive() + { return transitive; } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List lv) + public LazyValue lazyEval(final Context c, final Context.Type type, final Expression e, final Tokenizer.Token t, final List lv) { try { - Value res = fun.apply(c, type, e, t, unpackArgs(lv, c, Context.NONE)); + final Value res = fun.apply(c, type, e, t, unpackArgs(lv, c, Context.NONE)); return (cc, tt) -> res; } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -296,37 +328,39 @@ public class Expression }); } - public void addLazyBinaryOperator(String surface, int precedence, boolean leftAssoc, boolean pure, Function typer, - QuadFunction lazyfun) + public void addLazyBinaryOperator(final String surface, final int precedence, final boolean leftAssoc, final boolean pure, final Function typer, + final QuadFunction lazyfun) { operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) { @Override - public boolean pure() { + public boolean pure() + { return pure; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public Context.Type staticType(Context.Type outerType) + public Context.Type staticType(final Context.Type outerType) { return typer.apply(outerType); } @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression e, Tokenizer.Token token, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(final Context c, final Context.Type t, final Expression e, final Tokenizer.Token token, final LazyValue v1, final LazyValue v2) { ILazyFunction.checkInterrupts(); try { return lazyfun.apply(c, t, v1, v2); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, token); } @@ -334,30 +368,32 @@ public class Expression }); } - public void addBinaryContextOperator(String surface, int precedence, boolean leftAssoc, boolean pure, boolean transitive, - QuadFunction fun) + public void addBinaryContextOperator(final String surface, final int precedence, final boolean leftAssoc, final boolean pure, final boolean transitive, + final QuadFunction fun) { operators.put(surface, new AbstractLazyOperator(precedence, leftAssoc) { @Override - public boolean pure() { + public boolean pure() + { return pure; } @Override - public boolean transitive() { + public boolean transitive() + { return transitive; } @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression e, Tokenizer.Token token, LazyValue v1, LazyValue v2) + public LazyValue lazyEval(final Context c, final Context.Type t, final Expression e, final Tokenizer.Token token, final LazyValue v1, final LazyValue v2) { try { - Value ret = fun.apply(c, t, v1.evalValue(c, Context.NONE), v2.evalValue(c, Context.NONE)); + final Value ret = fun.apply(c, t, v1.evalValue(c, Context.NONE), v2.evalValue(c, Context.NONE)); return (cc, tt) -> ret; } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, token); } @@ -365,144 +401,176 @@ public class Expression }); } - public static RuntimeException handleCodeException(Context c, RuntimeException exc, Expression e, Tokenizer.Token token) + public static RuntimeException handleCodeException(final Context c, final RuntimeException exc, final Expression e, final Tokenizer.Token token) { if (exc instanceof ExitStatement) + { return exc; + } if (exc instanceof IntegrityException) + { return exc; - if (exc instanceof InternalExpressionException) - return ((InternalExpressionException) exc).promote(c, e, token); + } + if (exc instanceof final InternalExpressionException iee) + { + return iee.promote(c, e, token); + } if (exc instanceof ArithmeticException) - return new ExpressionException(c, e, token, "Your math is wrong, "+exc.getMessage()); + { + return new ExpressionException(c, e, token, "Your math is wrong, " + exc.getMessage()); + } if (exc instanceof ResolvedException) + { return exc; + } // unexpected really - should be caught earlier and converted to InternalExpressionException CarpetSettings.LOG.error("Unexpected exception while running Scarpet code", exc); return new ExpressionException(c, e, token, "Internal error (please report this issue to Carpet) while evaluating: " + exc); } - public void addUnaryOperator(String surface, boolean leftAssoc, Function fun) + public void addUnaryOperator(final String surface, final boolean leftAssoc, final Function fun) { - operators.put(surface+"u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!..."), leftAssoc) + operators.put(surface + "u", new AbstractUnaryOperator(Operators.precedence.get("unary+-!..."), leftAssoc) { @Override - public Value evalUnary(Value v1) + public Value evalUnary(final Value v1) { return fun.apply(v1); } }); } - public void addBinaryOperator(String surface, int precedence, boolean leftAssoc, BiFunction fun) + public void addBinaryOperator(final String surface, final int precedence, final boolean leftAssoc, final BiFunction fun) { operators.put(surface, new AbstractOperator(precedence, leftAssoc) { @Override - public Value eval(Value v1, Value v2) { return fun.apply(v1, v2); } + public Value eval(final Value v1, final Value v2) + { + return fun.apply(v1, v2); + } }); } - public void addUnaryFunction(String name, Function fun) + public void addUnaryFunction(final String name, final Function fun) { - functions.put(name, new AbstractFunction(1, name) + functions.put(name, new AbstractFunction(1, name) { @Override - public Value eval(List parameters) { return fun.apply(parameters.get(0)); } + public Value eval(final List parameters) + { + return fun.apply(parameters.get(0)); + } }); } - public void addImpureUnaryFunction(String name, Function fun) + public void addImpureUnaryFunction(final String name, final Function fun) { - functions.put(name, new AbstractFunction(1, name) + functions.put(name, new AbstractFunction(1, name) { @Override - public boolean pure() { + public boolean pure() + { return false; } @Override - public Value eval(List parameters) { return fun.apply(parameters.get(0)); } + public Value eval(final List parameters) + { + return fun.apply(parameters.get(0)); + } }); } - public void addBinaryFunction(String name, BiFunction fun) + public void addBinaryFunction(final String name, final BiFunction fun) { functions.put(name, new AbstractFunction(2, name) { @Override - public Value eval(List parameters) { return fun.apply(parameters.get(0), parameters.get(1)); } + public Value eval(final List parameters) + { + return fun.apply(parameters.get(0), parameters.get(1)); + } }); } - public void addFunction(String name, Function, Value> fun) + public void addFunction(final String name, final Function, Value> fun) { functions.put(name, new AbstractFunction(-1, name) { @Override - public Value eval(List parameters) { return fun.apply(parameters); } + public Value eval(final List parameters) + { + return fun.apply(parameters); + } }); } - public void addImpureFunction(String name, Function, Value> fun) + public void addImpureFunction(final String name, final Function, Value> fun) { functions.put(name, new AbstractFunction(-1, name) { @Override - public boolean pure() { + public boolean pure() + { return false; } @Override - public Value eval(List parameters) { return fun.apply(parameters); } + public Value eval(final List parameters) + { + return fun.apply(parameters); + } }); } - public void addMathematicalUnaryFunction(String name, Function fun) + public void addMathematicalUnaryFunction(final String name, final DoubleUnaryOperator fun) { - addUnaryFunction(name, (v) -> new NumericValue(fun.apply(NumericValue.asNumber(v).getDouble()))); + addUnaryFunction(name, (v) -> new NumericValue(fun.applyAsDouble(NumericValue.asNumber(v).getDouble()))); } - public void addMathematicalUnaryIntFunction(String name, Function fun) + public void addMathematicalUnaryIntFunction(final String name, final DoubleToLongFunction fun) { - addUnaryFunction(name, (v) -> new NumericValue(fun.apply(NumericValue.asNumber(v).getDouble()))); + addUnaryFunction(name, (v) -> new NumericValue(fun.applyAsLong(NumericValue.asNumber(v).getDouble()))); } - public void addMathematicalBinaryIntFunction(String name, BiFunction fun) + public void addMathematicalBinaryIntFunction(final String name, final BinaryOperator fun) { addBinaryFunction(name, (w, v) -> new NumericValue(fun.apply(NumericValue.asNumber(w).getLong(), NumericValue.asNumber(v).getLong()))); } - - public void addMathematicalBinaryFunction(String name, BiFunction fun) + + public void addMathematicalBinaryFunction(final String name, final BinaryOperator fun) { addBinaryFunction(name, (w, v) -> new NumericValue(fun.apply(NumericValue.asNumber(w).getDouble(), NumericValue.asNumber(v).getDouble()))); } - public void addLazyFunction(String name, int numParams, TriFunction, LazyValue> fun) + public void addLazyFunction(final String name, final int numParams, final TriFunction, LazyValue> fun) { functions.put(name, new AbstractLazyFunction(numParams, name) { @Override - public boolean pure() { + public boolean pure() + { return false; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(final Context c, final Context.Type i, final Expression e, final Tokenizer.Token t, final List lazyParams) { ILazyFunction.checkInterrupts(); if (numParams >= 0 && lazyParams.size() != numParams) { - String error = "Function '"+name+"' requires "+numParams+" arguments, got "+lazyParams.size()+". "; + final String error = "Function '" + name + "' requires " + numParams + " arguments, got " + lazyParams.size() + ". "; throw new InternalExpressionException(error + (fun instanceof Fluff.UsageProvider up ? up.getUsage() : "")); } @@ -510,7 +578,7 @@ public class Expression { return fun.apply(c, i, lazyParams); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -518,29 +586,31 @@ public class Expression }); } - public void addLazyFunction(String name, TriFunction, LazyValue> fun) + public void addLazyFunction(final String name, final TriFunction, LazyValue> fun) { functions.put(name, new AbstractLazyFunction(-1, name) { @Override - public boolean pure() { + public boolean pure() + { return false; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(final Context c, final Context.Type i, final Expression e, final Tokenizer.Token t, final List lazyParams) { ILazyFunction.checkInterrupts(); try { return fun.apply(c, i, lazyParams); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -548,35 +618,37 @@ public class Expression }); } - public void addPureLazyFunction(String name, int num_params, Function typer, TriFunction, LazyValue> fun) + public void addPureLazyFunction(final String name, final int num_params, final Function typer, final TriFunction, LazyValue> fun) { functions.put(name, new AbstractLazyFunction(num_params, name) { @Override - public boolean pure() { + public boolean pure() + { return true; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public Context.Type staticType(Context.Type outerType) + public Context.Type staticType(final Context.Type outerType) { return typer.apply(outerType); } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(final Context c, final Context.Type i, final Expression e, final Tokenizer.Token t, final List lazyParams) { ILazyFunction.checkInterrupts(); try { return fun.apply(c, i, lazyParams); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -584,30 +656,32 @@ public class Expression }); } - public void addContextFunction(String name, int num_params, TriFunction, Value> fun) + public void addContextFunction(final String name, final int num_params, final TriFunction, Value> fun) { functions.put(name, new AbstractLazyFunction(num_params, name) { @Override - public boolean pure() { + public boolean pure() + { return false; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(final Context c, final Context.Type i, final Expression e, final Tokenizer.Token t, final List lazyParams) { ILazyFunction.checkInterrupts(); try { - Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, Context.NONE)); + final Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, Context.NONE)); return (cc, tt) -> ret; } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -615,34 +689,37 @@ public class Expression }); } - public void addTypedContextFunction(String name, int num_params, Context.Type reqType, TriFunction, Value> fun) + public void addTypedContextFunction(final String name, final int num_params, final Context.Type reqType, final TriFunction, Value> fun) { functions.put(name, new AbstractLazyFunction(num_params, name) { @Override - public boolean pure() { + public boolean pure() + { return true; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public Context.Type staticType(Context.Type outerType) { + public Context.Type staticType(final Context.Type outerType) + { return reqType; } @Override - public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List lazyParams) + public LazyValue lazyEval(final Context c, final Context.Type i, final Expression e, final Tokenizer.Token t, final List lazyParams) { try { - Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, reqType)); + final Value ret = fun.apply(c, i, unpackArgs(lazyParams, c, reqType)); return (cc, tt) -> ret; } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw handleCodeException(c, exc, e, t); } @@ -650,34 +727,42 @@ public class Expression }); } - public FunctionValue createUserDefinedFunction(Context context, String name, Expression expr, Tokenizer.Token token, List arguments, String varArgs, List outers, LazyValue code) + public FunctionValue createUserDefinedFunction(final Context context, final String name, final Expression expr, final Tokenizer.Token token, final List arguments, final String varArgs, final List outers, final LazyValue code) { if (functions.containsKey(name)) - throw new ExpressionException(context, expr, token, "Function "+name+" would mask a built-in function"); - Map contextValues = new HashMap<>(); - for (String outer : outers) { - LazyValue lv = context.getVariable(outer); + throw new ExpressionException(context, expr, token, "Function " + name + " would mask a built-in function"); + } + Map contextValues = new HashMap<>(); + for (final String outer : outers) + { + final LazyValue lv = context.getVariable(outer); if (lv == null) { - throw new InternalExpressionException("Variable "+outer+" needs to be defined in outer scope to be used as outer parameter, and cannot be global"); + throw new InternalExpressionException("Variable " + outer + " needs to be defined in outer scope to be used as outer parameter, and cannot be global"); } else { contextValues.put(outer, lv); } } - if (contextValues.isEmpty()) contextValues = null; + if (contextValues.isEmpty()) + { + contextValues = null; + } - FunctionValue result = new FunctionValue(expr, token, name, code, arguments, varArgs, contextValues); + final FunctionValue result = new FunctionValue(expr, token, name, code, arguments, varArgs, contextValues); // do not store lambda definitions - if (!name.equals("_")) context.host.addUserDefinedFunction(context, module, name, result); + if (!name.equals("_")) + { + context.host.addUserDefinedFunction(context, module, name, result); + } return result; } - public void alias(String copy, String original) + public void alias(final String copy, final String original) { - ILazyFunction originalFunction = functions.get(original); + final ILazyFunction originalFunction = functions.get(original); functions.put(copy, new ILazyFunction() { @Override @@ -693,31 +778,34 @@ public class Expression } @Override - public boolean pure() { + public boolean pure() + { return originalFunction.pure(); } @Override - public boolean transitive() { + public boolean transitive() + { return originalFunction.transitive(); } @Override - public Context.Type staticType(Context.Type outerType) { + public Context.Type staticType(final Context.Type outerType) + { return originalFunction.staticType(outerType); } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression expr, Tokenizer.Token token, List lazyParams) + public LazyValue lazyEval(final Context c, final Context.Type type, final Expression expr, final Tokenizer.Token token, final List lazyParams) { - c.host.issueDeprecation(copy+"(...)"); + c.host.issueDeprecation(copy + "(...)"); return originalFunction.lazyEval(c, type, expr, token, lazyParams); } }); } - public void setAnyVariable(Context c, String name, LazyValue lv) + public void setAnyVariable(final Context c, final String name, final LazyValue lv) { if (name.startsWith("global_")) { @@ -729,28 +817,35 @@ public class Expression } } - public LazyValue getOrSetAnyVariable(Context c, String name) + public LazyValue getOrSetAnyVariable(final Context c, final String name) { - LazyValue var; + LazyValue variable; if (!name.startsWith("global_")) { - var = c.getVariable(name); - if (var != null) return var; + variable = c.getVariable(name); + if (variable != null) + { + return variable; + } } - var = c.host.getGlobalVariable(module, name); - if (var != null) return var; - var = (_c, _t ) -> _c.host.strict ? Value.UNDEF.reboundedTo(name) : Value.NULL.reboundedTo(name); - setAnyVariable(c, name, var); - return var; + variable = c.host.getGlobalVariable(module, name); + if (variable != null) + { + return variable; + } + variable = (_c, _t) -> _c.host.strict ? Value.UNDEF.reboundedTo(name) : Value.NULL.reboundedTo(name); + setAnyVariable(c, name, variable); + return variable; } public static final Expression none = new Expression("null"); + /** * @param expression . */ - public Expression(String expression) + public Expression(final String expression) { - this.expression = expression.stripTrailing().replaceAll("\\r\\n?", "\n").replaceAll("\\t"," "); + this.expression = expression.stripTrailing().replaceAll("\\r\\n?", "\n").replaceAll("\\t", " "); Operators.apply(this); ControlFlow.apply(this); Functions.apply(this); @@ -762,26 +857,25 @@ public class Expression } - private List shuntingYard(Context c) + private List shuntingYard(final Context c) { - List outputQueue = new ArrayList<>(); - Stack stack = new ObjectArrayList<>(); + final List outputQueue = new ArrayList<>(); + final Stack stack = new ObjectArrayList<>(); - Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions); + final Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions); // stripping lousy but acceptable semicolons - List cleanedTokens = tokenizer.postProcess(); + final List cleanedTokens = tokenizer.postProcess(); Tokenizer.Token lastFunction = null; Tokenizer.Token previousToken = null; - for (Tokenizer.Token token : cleanedTokens) + for (final Tokenizer.Token token : cleanedTokens) { switch (token.type) { case STRINGPARAM: //stack.push(token); // changed that so strings are treated like literals //break; - case LITERAL: - case HEX_LITERAL: + case LITERAL, HEX_LITERAL: if (previousToken != null && ( previousToken.type == Tokenizer.Token.TokenType.LITERAL || previousToken.type == Tokenizer.Token.TokenType.HEX_LITERAL || @@ -824,9 +918,9 @@ public class Expression if (previousToken != null && (previousToken.type == Tokenizer.Token.TokenType.COMMA || previousToken.type == Tokenizer.Token.TokenType.OPEN_PAREN)) { - throw new ExpressionException(c, this, token, "Missing parameter(s) for operator '" + token+"'"); + throw new ExpressionException(c, this, token, "Missing parameter(s) for operator '" + token + "'"); } - ILazyOperator o1 = operators.get(token.surface); + final ILazyOperator o1 = operators.get(token.surface); if (o1 == null) { throw new ExpressionException(c, this, token, "Unknown operator '" + token + "'"); @@ -841,9 +935,9 @@ public class Expression if (previousToken != null && previousToken.type != Tokenizer.Token.TokenType.OPERATOR && previousToken.type != Tokenizer.Token.TokenType.COMMA && previousToken.type != Tokenizer.Token.TokenType.OPEN_PAREN) { - throw new ExpressionException(c, this, token, "Invalid position for unary operator " + token ); + throw new ExpressionException(c, this, token, "Invalid position for unary operator " + token); } - ILazyOperator o1 = operators.get(token.surface); + final ILazyOperator o1 = operators.get(token.surface); if (o1 == null) { throw new ExpressionException(c, this, token, "Unknown unary operator '" + token.surface.substring(0, token.surface.length() - 1) + "'"); @@ -854,24 +948,10 @@ public class Expression break; } case OPEN_PAREN: - if (previousToken != null) + // removed implicit multiplication in this missing code block + if (previousToken != null && previousToken.type == Tokenizer.Token.TokenType.FUNCTION) { - //if (previousToken.type == Tokenizer.Token.TokenType.LITERAL || previousToken.type == Tokenizer.Token.TokenType.CLOSE_PAREN - // || previousToken.type == Tokenizer.Token.TokenType.VARIABLE - // || previousToken.type == Tokenizer.Token.TokenType.HEX_LITERAL) - //{ - // Implicit multiplication, e.g. 23(a+b) or (a+b)(a-b) - // Tokenizer.Token multiplication = new Tokenizer.Token(); - // multiplication.append("*"); - // multiplication.type = Tokenizer.Token.TokenType.OPERATOR; - // stack.push(multiplication); - //} - // if the ( is preceded by a valid function, then it - // denotes the start of a parameter list - if (previousToken.type == Tokenizer.Token.TokenType.FUNCTION) - { - outputQueue.add(token); - } + outputQueue.add(token); } stack.push(token); break; @@ -897,18 +977,21 @@ public class Expression case MARKER: if ("$".equals(token.surface)) { - StringBuilder sb = new StringBuilder(expression); + final StringBuilder sb = new StringBuilder(expression); sb.setCharAt(token.pos, '\n'); expression = sb.toString(); } break; } - if (token.type != Tokenizer.Token.TokenType.MARKER) previousToken = token; + if (token.type != Tokenizer.Token.TokenType.MARKER) + { + previousToken = token; + } } while (!stack.isEmpty()) { - Tokenizer.Token element = stack.pop(); + final Tokenizer.Token element = stack.pop(); if (element.type == Tokenizer.Token.TokenType.OPEN_PAREN || element.type == Tokenizer.Token.TokenType.CLOSE_PAREN) { throw new ExpressionException(c, this, element, "Mismatched parentheses"); @@ -918,7 +1001,7 @@ public class Expression return outputQueue; } - private void shuntOperators(List outputQueue, Stack stack, ILazyOperator o1) + private void shuntOperators(final List outputQueue, final Stack stack, final ILazyOperator o1) { Tokenizer.Token nextToken = stack.isEmpty() ? null : stack.top(); while (nextToken != null @@ -932,7 +1015,7 @@ public class Expression } } - public Value eval(Context c) + public Value eval(final Context c) { if (ast == null) { @@ -941,31 +1024,31 @@ public class Expression return evalValue(() -> ast, c, Context.Type.NONE); } - public Value evalValue(Supplier exprProvider, Context c, Context.Type expectedType) + public Value evalValue(final Supplier exprProvider, final Context c, final Context.Type expectedType) { try { return exprProvider.get().evalValue(c, expectedType); } - catch (ContinueStatement | BreakStatement | ReturnStatement exc) + catch (final ContinueStatement | BreakStatement | ReturnStatement exc) { throw new ExpressionException(c, this, "Control flow functions, like continue, break or return, should only be used in loops, and functions respectively."); } - catch (ExitStatement exit) + catch (final ExitStatement exit) { - return exit.retval==null?Value.NULL:exit.retval; + return exit.retval == null ? Value.NULL : exit.retval; } - catch (StackOverflowError ignored) + catch (final StackOverflowError ignored) { throw new ExpressionException(c, this, "Your thoughts are too deep"); } - catch (InternalExpressionException exc) + catch (final InternalExpressionException exc) { - throw new ExpressionException(c, this, "Your expression result is incorrect: "+exc.getMessage()); + throw new ExpressionException(c, this, "Your expression result is incorrect: " + exc.getMessage()); } - catch (ArithmeticException exc) + catch (final ArithmeticException exc) { - throw new ExpressionException(c, this, "The final result is incorrect: "+exc.getMessage()); + throw new ExpressionException(c, this, "The final result is incorrect: " + exc.getMessage()); } } @@ -980,7 +1063,8 @@ public class Expression * varying numbers of function parameters. */ public static final ExpressionNode PARAMS_START = new ExpressionNode(null, null, Tokenizer.Token.NONE); - public ExpressionNode(LazyValue op, List args, Tokenizer.Token token) + + public ExpressionNode(final LazyValue op, final List args, final Tokenizer.Token token) { this.op = op; this.args = args; @@ -988,49 +1072,48 @@ public class Expression range = new ArrayList<>(); range.add(token); } - public static ExpressionNode ofConstant(Value val, Tokenizer.Token token) + + public static ExpressionNode ofConstant(final Value val, final Tokenizer.Token token) { return new ExpressionNode(new LazyValue.Constant(val), Collections.emptyList(), token); } } - private ExpressionNode RPNToParseTree(List tokens, Context context) + private ExpressionNode RPNToParseTree(final List tokens, final Context context) { - Stack nodeStack = new ObjectArrayList<>(); + final Stack nodeStack = new ObjectArrayList<>(); for (final Tokenizer.Token token : tokens) { - switch (token.type) - { - case UNARY_OPERATOR: - { + switch (token.type) { + case UNARY_OPERATOR -> { final ExpressionNode node = nodeStack.pop(); - LazyValue result = (c, t) -> operators.get(token.surface).lazyEval(c, t, this, token, node.op, null).evalValue(c, t); + final LazyValue result = (c, t) -> operators.get(token.surface).lazyEval(c, t, this, token, node.op, null).evalValue(c, t); nodeStack.push(new ExpressionNode(result, Collections.singletonList(node), token)); - break; } - case OPERATOR: + case OPERATOR -> { final ExpressionNode v1 = nodeStack.pop(); final ExpressionNode v2 = nodeStack.pop(); - LazyValue result = (c,t) -> operators.get(token.surface).lazyEval(c, t,this, token, v2.op, v1.op).evalValue(c, t); - nodeStack.push(new ExpressionNode(result, List.of(v2, v1), token )); - break; - case VARIABLE: - Value constant = getConstantFor(token.surface); + final LazyValue result = (c, t) -> operators.get(token.surface).lazyEval(c, t, this, token, v2.op, v1.op).evalValue(c, t); + nodeStack.push(new ExpressionNode(result, List.of(v2, v1), token)); + } + case VARIABLE -> { + final Value constant = getConstantFor(token.surface); if (constant != null) { token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); nodeStack.push(new ExpressionNode(LazyValue.ofConstant(constant), Collections.emptyList(), token)); } - else { + else + { nodeStack.push(new ExpressionNode(((c, t) -> getOrSetAnyVariable(c, token.surface).evalValue(c, t)), Collections.emptyList(), token)); } - break; - case FUNCTION: - String name = token.surface; - ILazyFunction f; - ArrayList p; - boolean isKnown = functions.containsKey(name); // globals will be evaluated lazily, not at compile time via . + } + case FUNCTION -> { + final String name = token.surface; + final ILazyFunction f; + final ArrayList p; + final boolean isKnown = functions.containsKey(name); // globals will be evaluated lazily, not at compile time via . if (isKnown) { f = functions.get(name); @@ -1053,190 +1136,230 @@ public class Expression token.morph(Tokenizer.Token.TokenType.FUNCTION, "call"); } Collections.reverse(p); - if (nodeStack.top() == ExpressionNode.PARAMS_START) { nodeStack.pop(); - }; - List params = p.stream().map(n -> n.op).collect(Collectors.toList()); - + } + final List params = p.stream().map(n -> n.op).collect(Collectors.toList()); nodeStack.push(new ExpressionNode( (c, t) -> f.lazyEval(c, t, this, token, params).evalValue(c, t), - p,token + p, token )); - break; - case OPEN_PAREN: - nodeStack.push(ExpressionNode.PARAMS_START); - break; - case LITERAL: - Value number; + } + case OPEN_PAREN -> nodeStack.push(ExpressionNode.PARAMS_START); + case LITERAL -> { + final Value number; try { number = new NumericValue(token.surface); } - catch (NumberFormatException exception) + catch (final NumberFormatException exception) { throw new ExpressionException(context, this, token, "Not a number"); } token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); nodeStack.push(ExpressionNode.ofConstant(number, token)); - break; - case STRINGPARAM: + } + case STRINGPARAM -> { token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); nodeStack.push(ExpressionNode.ofConstant(new StringValue(token.surface), token)); - break; - case HEX_LITERAL: - Value hexNumber; + } + case HEX_LITERAL -> { + final Value hexNumber; try { hexNumber = new NumericValue(new BigInteger(token.surface.substring(2), 16).longValue()); } - catch (NumberFormatException exception) + catch (final NumberFormatException exception) { throw new ExpressionException(context, this, token, "Not a number"); } token.morph(Tokenizer.Token.TokenType.CONSTANT, token.surface); nodeStack.push(ExpressionNode.ofConstant(hexNumber, token)); - break; - default: - throw new ExpressionException(context, this, token, "Unexpected token '" + token.surface + "'"); + } + default -> throw new ExpressionException(context, this, token, "Unexpected token '" + token.surface + "'"); } } return nodeStack.pop(); } - private LazyValue getAST(Context context) + private LazyValue getAST(final Context context) { - //Stack stack = new Stack<>(); - List rpn = shuntingYard(context); + final List rpn = shuntingYard(context); validate(context, rpn); - ExpressionNode root = RPNToParseTree(rpn, context); + final ExpressionNode root = RPNToParseTree(rpn, context); if (!CarpetSettings.scriptsOptimization) + { return root.op; + } - Context optimizeOnlyContext = new Context.ContextForErrorReporting(context); + final Context optimizeOnlyContext = new Context.ContextForErrorReporting(context); if (CarpetSettings.scriptsDebugging) - CarpetScriptServer.LOG.info("Input code size for "+getModuleName()+": " + treeSize(root) + " nodes, " + treeDepth(root) + " deep"); + { + CarpetScriptServer.LOG.info("Input code size for " + getModuleName() + ": " + treeSize(root) + " nodes, " + treeDepth(root) + " deep"); + } // Defined out here to not need to conditionally assign them with debugging disabled int prevTreeSize = -1; int prevTreeDepth = -1; boolean changed = true; - while(changed) { + while (changed) + { changed = false; - while (true) { - if (CarpetSettings.scriptsDebugging) { + while (true) + { + if (CarpetSettings.scriptsDebugging) + { prevTreeSize = treeSize(root); prevTreeDepth = treeDepth(root); } - boolean optimized = compactTree(root, Context.Type.NONE, 0); - if (!optimized) break; + final boolean optimized = compactTree(root, Context.Type.NONE, 0); + if (!optimized) + { + break; + } changed = true; if (CarpetSettings.scriptsDebugging) + { CarpetScriptServer.LOG.info("Compacted from " + prevTreeSize + " nodes, " + prevTreeDepth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth"); + } } - while (true) { - if (CarpetSettings.scriptsDebugging) { + while (true) + { + if (CarpetSettings.scriptsDebugging) + { prevTreeSize = treeSize(root); prevTreeDepth = treeDepth(root); } - boolean optimized = optimizeTree(optimizeOnlyContext, root, Context.Type.NONE, 0); - if (!optimized) break; + final boolean optimized = optimizeTree(optimizeOnlyContext, root, Context.Type.NONE, 0); + if (!optimized) + { + break; + } changed = true; if (CarpetSettings.scriptsDebugging) + { CarpetScriptServer.LOG.info("Optimized from " + prevTreeSize + " nodes, " + prevTreeDepth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth"); + } } } return extractOp(optimizeOnlyContext, root, Context.Type.NONE); } - private int treeSize(ExpressionNode node) + private int treeSize(final ExpressionNode node) { - if (node.op instanceof LazyValue.ContextFreeLazyValue) return 1; - return node.args.stream().mapToInt(this::treeSize).sum()+1; + return node.op instanceof LazyValue.ContextFreeLazyValue ? 1 : node.args.stream().mapToInt(this::treeSize).sum() + 1; } - private int treeDepth(ExpressionNode node) + + private int treeDepth(final ExpressionNode node) { - if (node.op instanceof LazyValue.ContextFreeLazyValue) return 1; - return node.args.stream().mapToInt(this::treeDepth).max().orElse(0)+1; + return node.op instanceof LazyValue.ContextFreeLazyValue ? 1 : node.args.stream().mapToInt(this::treeDepth).max().orElse(0) + 1; } - private boolean compactTree(ExpressionNode node, Context.Type expectedType, int indent) { + private boolean compactTree(final ExpressionNode node, final Context.Type expectedType, final int indent) + { // ctx is just to report errors, not values evaluation boolean optimized = false; - Tokenizer.Token.TokenType token = node.token.type; - if (!token.isFunctional()) return false; + final Tokenizer.Token.TokenType token = node.token.type; + if (!token.isFunctional()) + { + return false; + } // input special cases here, like function signature - if (node.op instanceof LazyValue.Constant) return false; // optimized already + if (node.op instanceof LazyValue.Constant) + { + return false; // optimized already + } // function or operator - String symbol = node.token.surface; - Fluff.EvalNode operation = ((token == Tokenizer.Token.TokenType.FUNCTION) ? functions : operators).get(symbol); - Context.Type requestedType = operation.staticType(expectedType); - for (ExpressionNode arg : node.args) { - if (compactTree(arg, requestedType, indent+1)) optimized = true; + final String symbol = node.token.surface; + final Fluff.EvalNode operation = ((token == Tokenizer.Token.TokenType.FUNCTION) ? functions : operators).get(symbol); + final Context.Type requestedType = operation.staticType(expectedType); + for (final ExpressionNode arg : node.args) + { + if (compactTree(arg, requestedType, indent + 1)) + { + optimized = true; + } } - if (expectedType != Context.Type.MAPDEF && symbol.equals("->") && node.args.size() == 2) { - String rop = node.args.get(1).token.surface; + if (expectedType != Context.Type.MAPDEF && symbol.equals("->") && node.args.size() == 2) + { + final String rop = node.args.get(1).token.surface; ExpressionNode returnNode = null; - if ((rop.equals(";") || rop.equals("then"))) { - List thenArgs = node.args.get(1).args; - if (thenArgs.size() > 1 && thenArgs.get(thenArgs.size() - 1).token.surface.equals("return")) { + if ((rop.equals(";") || rop.equals("then"))) + { + final List thenArgs = node.args.get(1).args; + if (thenArgs.size() > 1 && thenArgs.get(thenArgs.size() - 1).token.surface.equals("return")) + { returnNode = thenArgs.get(thenArgs.size() - 1); } - } else if (rop.equals("return")) { + } + else if (rop.equals("return")) + { returnNode = node.args.get(1); } if (returnNode != null) // tail return { - if (returnNode.args.size() > 0) { + if (!returnNode.args.isEmpty()) + { returnNode.op = returnNode.args.get(0).op; returnNode.token = returnNode.args.get(0).token; returnNode.range = returnNode.args.get(0).range; returnNode.args = returnNode.args.get(0).args; if (CarpetSettings.scriptsDebugging) + { CarpetScriptServer.LOG.info(" - Removed unnecessary tail return of " + returnNode.token.surface + " from function body at line " + (returnNode.token.lineno + 1) + ", node depth " + indent); - - } else { + } + } + else + { returnNode.op = LazyValue.ofConstant(Value.NULL); returnNode.token.morph(Tokenizer.Token.TokenType.CONSTANT, ""); returnNode.args = Collections.emptyList(); if (CarpetSettings.scriptsDebugging) + { CarpetScriptServer.LOG.info(" - Removed unnecessary tail return from function body at line " + (returnNode.token.lineno + 1) + ", node depth " + indent); - + } } } } - for (Map.Entry pair : functionalEquivalence.entrySet()) { - String operator = pair.getKey(); - String function = pair.getValue(); + for (final Map.Entry pair : functionalEquivalence.entrySet()) + { + final String operator = pair.getKey(); + final String function = pair.getValue(); if ((symbol.equals(operator) || symbol.equals(function)) && node.args.size() > 0) { - boolean leftOptimizable = operators.get(operator).isLeftAssoc(); - ExpressionNode optimizedChild = node.args.get(leftOptimizable?0:(node.args.size()-1)); - String type = optimizedChild.token.surface; + final boolean leftOptimizable = operators.get(operator).isLeftAssoc(); + final ExpressionNode optimizedChild = node.args.get(leftOptimizable ? 0 : (node.args.size() - 1)); + final String type = optimizedChild.token.surface; if ((type.equals(operator) || type.equals(function)) && (!(optimizedChild.op instanceof LazyValue.ContextFreeLazyValue))) { optimized = true; - List newargs = new ArrayList<>(); + final List newargs = new ArrayList<>(); if (leftOptimizable) { newargs.addAll(optimizedChild.args); for (int i = 1; i < node.args.size(); i++) + { newargs.add(node.args.get(i)); + } } else { - for (int i = 0; i < node.args.size()-1; i++) + for (int i = 0; i < node.args.size() - 1; i++) + { newargs.add(node.args.get(i)); + } newargs.addAll(optimizedChild.args); } if (CarpetSettings.scriptsDebugging) + { CarpetScriptServer.LOG.info(" - " + symbol + "(" + node.args.size() + ") => " + function + "(" + newargs.size() + ") at line " + (node.token.lineno + 1) + ", node depth " + indent); + } node.token.morph(Tokenizer.Token.TokenType.FUNCTION, function); node.args = newargs; } @@ -1245,131 +1368,155 @@ public class Expression return optimized; } - private boolean optimizeTree(Context ctx, ExpressionNode node, Context.Type expectedType, int indent) { + private boolean optimizeTree(final Context ctx, final ExpressionNode node, Context.Type expectedType, final int indent) + { // ctx is just to report errors, not values evaluation boolean optimized = false; - Tokenizer.Token.TokenType token = node.token.type; - if (!token.isFunctional()) return false; - String symbol = node.token.surface; + final Tokenizer.Token.TokenType token = node.token.type; + if (!token.isFunctional()) + { + return false; + } + final String symbol = node.token.surface; // input special cases here, like function signature - if (node.op instanceof LazyValue.Constant) return false; // optimized already + if (node.op instanceof LazyValue.Constant) + { + return false; // optimized already + } // function or operator - Fluff.EvalNode operation = ((token == Tokenizer.Token.TokenType.FUNCTION) ? functions : operators).get(symbol); - Context.Type requestedType = operation.staticType(expectedType); - for (ExpressionNode arg : node.args) { - if (optimizeTree(ctx, arg, requestedType, indent+1)) optimized = true; + final Fluff.EvalNode operation = ((token == Tokenizer.Token.TokenType.FUNCTION) ? functions : operators).get(symbol); + final Context.Type requestedType = operation.staticType(expectedType); + for (final ExpressionNode arg : node.args) + { + if (optimizeTree(ctx, arg, requestedType, indent + 1)) + { + optimized = true; + } } - for (ExpressionNode arg : node.args) { - if (arg.token.type.isConstant()) continue; - if (arg.op instanceof LazyValue.ContextFreeLazyValue) continue; + for (final ExpressionNode arg : node.args) + { + if (arg.token.type.isConstant()) + { + continue; + } + if (arg.op instanceof LazyValue.ContextFreeLazyValue) + { + continue; + } return optimized; } // a few exceptions which we don't implement in the framework for simplicity for now if (!operation.pure()) { - if (symbol.equals("->") && expectedType == Context.Type.MAPDEF) + if (!symbol.equals("->") || expectedType != Context.Type.MAPDEF) { - - } - else { return optimized; } } - if (operation.pure()) + // element access with constant elements will always resolve the same way. + if (operation.pure() && symbol.equals(":") && expectedType == Context.Type.LVALUE) { - // element access with constant elements will always resolve the same way. - if (symbol.equals(":") && expectedType == Context.Type.LVALUE) - { - expectedType = Context.Type.NONE; - } + expectedType = Context.Type.NONE; } List args = new ArrayList<>(node.args.size()); - for (ExpressionNode arg : node.args) { - try { - if (arg.op instanceof LazyValue.Constant) { - Value val = ((LazyValue.Constant) arg.op).get(); + for (final ExpressionNode arg : node.args) + { + try + { + if (arg.op instanceof LazyValue.Constant) + { + final Value val = ((LazyValue.Constant) arg.op).get(); args.add((c, t) -> val); } - else args.add((c, t) -> arg.op.evalValue(ctx, requestedType)); - } catch (NullPointerException npe) { + else + { + args.add((c, t) -> arg.op.evalValue(ctx, requestedType)); + } + } + catch (final NullPointerException npe) + { throw new ExpressionException(ctx, this, node.token, "Attempted to evaluate context free expression"); } } // applying argument unpacking - args= AbstractLazyFunction.lazify(AbstractLazyFunction.unpackLazy(args, ctx, requestedType)); - Value result; + args = AbstractLazyFunction.lazify(AbstractLazyFunction.unpackLazy(args, ctx, requestedType)); + final Value result; if (operation instanceof ILazyFunction) { result = ((ILazyFunction) operation).lazyEval(ctx, expectedType, this, node.token, args).evalValue(null, expectedType); } else if (args.size() == 1) { - result = ((ILazyOperator)operation).lazyEval(ctx, expectedType, this, node.token, args.get(0), null).evalValue(null, expectedType); + result = ((ILazyOperator) operation).lazyEval(ctx, expectedType, this, node.token, args.get(0), null).evalValue(null, expectedType); } else // args == 2 { - result = ((ILazyOperator)operation).lazyEval(ctx, expectedType, this, node.token, args.get(0), args.get(1)).evalValue(null, expectedType); + result = ((ILazyOperator) operation).lazyEval(ctx, expectedType, this, node.token, args.get(0), args.get(1)).evalValue(null, expectedType); } node.op = LazyValue.ofConstant(result); - //node.token.morph(Tokenizer.Token.TokenType.CONSTANT, node.token.surface); if (CarpetSettings.scriptsDebugging) - CarpetScriptServer.LOG.info(" - "+symbol+"("+args.stream().map(a -> a.evalValue(null, requestedType).getString()).collect(Collectors.joining(", "))+") => "+result.getString()+" at line "+(node.token.lineno+1) +", node depth "+indent); + { + CarpetScriptServer.LOG.info(" - " + symbol + "(" + args.stream().map(a -> a.evalValue(null, requestedType).getString()).collect(Collectors.joining(", ")) + ") => " + result.getString() + " at line " + (node.token.lineno + 1) + ", node depth " + indent); + } return true; } - private LazyValue extractOp(Context ctx, ExpressionNode node, Context.Type expectedType) + private LazyValue extractOp(final Context ctx, final ExpressionNode node, final Context.Type expectedType) { if (node.op instanceof LazyValue.Constant) { // constants are immutable if (node.token.type.isConstant()) { - Value value = ((LazyValue.Constant) node.op).get(); + final Value value = ((LazyValue.Constant) node.op).get(); return (c, t) -> value; } return node.op; } if (node.op instanceof LazyValue.ContextFreeLazyValue) { - Value ret = ((LazyValue.ContextFreeLazyValue) node.op).evalType(expectedType); + final Value ret = ((LazyValue.ContextFreeLazyValue) node.op).evalType(expectedType); return (c, t) -> ret; } - Tokenizer.Token token = node.token; + final Tokenizer.Token token = node.token; switch (token.type) { - case UNARY_OPERATOR: { - ILazyOperator op = operators.get(token.surface); - Context.Type requestedType = op.staticType(expectedType); - LazyValue arg = extractOp(ctx, node.args.get(0), requestedType); + case UNARY_OPERATOR: + { + final ILazyOperator op = operators.get(token.surface); + final Context.Type requestedType = op.staticType(expectedType); + final LazyValue arg = extractOp(ctx, node.args.get(0), requestedType); return (c, t) -> op.lazyEval(c, t, this, token, arg, null).evalValue(c, t); } - case OPERATOR: { - ILazyOperator op = operators.get(token.surface); - Context.Type requestedType = op.staticType(expectedType); - LazyValue arg = extractOp(ctx, node.args.get(0), requestedType); - LazyValue arh = extractOp(ctx, node.args.get(1), requestedType); + case OPERATOR: + { + final ILazyOperator op = operators.get(token.surface); + final Context.Type requestedType = op.staticType(expectedType); + final LazyValue arg = extractOp(ctx, node.args.get(0), requestedType); + final LazyValue arh = extractOp(ctx, node.args.get(1), requestedType); return (c, t) -> op.lazyEval(c, t, this, token, arg, arh).evalValue(c, t); } case VARIABLE: return (c, t) -> getOrSetAnyVariable(c, token.surface).evalValue(c, t); - case FUNCTION: { - ILazyFunction f = functions.get(token.surface); - Context.Type requestedType = f.staticType(expectedType); - List params = node.args.stream().map(n -> extractOp(ctx, n, requestedType)).collect(Collectors.toList()); + case FUNCTION: + { + final ILazyFunction f = functions.get(token.surface); + final Context.Type requestedType = f.staticType(expectedType); + final List params = node.args.stream().map(n -> extractOp(ctx, n, requestedType)).collect(Collectors.toList()); return (c, t) -> f.lazyEval(c, t, this, token, params).evalValue(c, t); } case CONSTANT: return node.op; default: - throw new ExpressionException(ctx, this, node.token, "Unexpected token '" + node.token.type +" "+node.token.surface + "'"); + throw new ExpressionException(ctx, this, node.token, "Unexpected token '" + node.token.type + " " + node.token.surface + "'"); } } - private void validate(Context c, List rpn) + private void validate(final Context c, final List rpn) { /*- * Thanks to Norman Ramsey: @@ -1379,7 +1526,7 @@ public class Expression // each // layer on the stack being the count of the number of parameters in // that scope - IntArrayList stack = new IntArrayList(); // IntArrayList instead of just IntStack because we need to query the size + final IntArrayList stack = new IntArrayList(); // IntArrayList instead of just IntStack because we need to query the size // push the 'global' scope stack.push(0); diff --git a/src/main/java/carpet/script/Fluff.java b/src/main/java/carpet/script/Fluff.java index 9fa199bc..ca91195e 100644 --- a/src/main/java/carpet/script/Fluff.java +++ b/src/main/java/carpet/script/Fluff.java @@ -13,24 +13,33 @@ import java.util.List; public abstract class Fluff { @FunctionalInterface - public interface TriFunction { R apply(A a, B b, C c); } + public interface TriFunction + { + R apply(A a, B b, C c); + } @FunctionalInterface - public interface TriConsumer { void accept(A a, B b, C c); } + public interface QuadFunction + { + R apply(A a, B b, C c, D d); + } @FunctionalInterface - public interface QuadConsumer { void accept(A a, B b, C c, D d); } + public interface QuinnFunction + { + R apply(A a, B b, C c, D d, E e); + } @FunctionalInterface - public interface QuadFunction { R apply(A a, B b, C c, D d);} + public interface SexFunction + { + R apply(A a, B b, C c, D d, E e, F f); + } - @FunctionalInterface - public interface QuinnFunction { R apply(A a, B b, C c, D d, E e);} - - @FunctionalInterface - public interface SexFunction { R apply(A a, B b, C c, D d, E e, F f);} - - public interface UsageProvider { String getUsage();} + public interface UsageProvider + { + String getUsage(); + } public interface EvalNode { @@ -49,7 +58,11 @@ public abstract class Fluff /** * @return required argument eval type in case its evaluated statically without context but with a given context type */ - default Context.Type staticType(Context.Type outerType) {return transitive()?outerType:Context.NONE;}; + default Context.Type staticType(final Context.Type outerType) + { + return transitive() ? outerType : Context.NONE; + } + } public interface ILazyFunction extends EvalNode @@ -63,9 +76,11 @@ public abstract class Fluff static void checkInterrupts() { if (ScriptHost.mainThread != Thread.currentThread() && Thread.currentThread().isInterrupted()) + { throw new InternalExpressionException("Thread interrupted"); + } } - // lazy function has a chance to change execution based on contxt + // lazy function has a chance to change execution based on context } public interface IFunction extends ILazyFunction @@ -92,94 +107,109 @@ public abstract class Fluff protected String name; int numParams; - public AbstractLazyFunction(int numParams, String name) + public AbstractLazyFunction(final int numParams, final String name) { + super(); this.numParams = numParams; this.name = name; } - public String getName() { + public String getName() + { return name; } @Override - public int getNumParams() { + public int getNumParams() + { return numParams; } @Override - public boolean numParamsVaries() { + public boolean numParamsVaries() + { return numParams < 0; } - public static List unpackLazy(List lzargs, Context c, Context.Type contextType) + public static List unpackLazy(final List lzargs, final Context c, final Context.Type contextType) { - List args = new ArrayList<>(); - for (LazyValue lv : lzargs) + final List args = new ArrayList<>(); + for (final LazyValue lv : lzargs) { - Value arg = lv.evalValue(c, contextType); + final Value arg = lv.evalValue(c, contextType); if (arg instanceof FunctionUnpackedArgumentsValue) + { args.addAll(((ListValue) arg).getItems()); + } else + { args.add(arg); + } } return args; } - public List unpackArgs(List lzargs, Context c, Context.Type contextType) + public List unpackArgs(final List lzargs, final Context c, final Context.Type contextType) { - List args = unpackLazy(lzargs, c, contextType); + final List args = unpackLazy(lzargs, c, contextType); if (!numParamsVaries() && getNumParams() != args.size()) + { throw new InternalExpressionException("Function " + getName() + " expected " + getNumParams() + " parameters, got " + args.size()); + } return args; } - public static List lazify(List args) + public static List lazify(final List args) { - List lzargs = new ArrayList<>(args.size()); - args.forEach( v -> lzargs.add( (c, t) -> v)); + final List lzargs = new ArrayList<>(args.size()); + args.forEach(v -> lzargs.add((c, t) -> v)); return lzargs; } } public abstract static class AbstractFunction extends AbstractLazyFunction implements IFunction { - AbstractFunction(int numParams, String name) { + AbstractFunction(final int numParams, final String name) + { super(numParams, name); } @Override - public boolean pure() { + public boolean pure() + { return true; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Tokenizer.Token t, final List lazyParams) + public LazyValue lazyEval(final Context cc, final Context.Type type, final Expression e, final Tokenizer.Token t, final List lazyParams) { return new LazyValue() { // eager evaluation always ignores the required type and evals params by none default private List params; + @Override - public Value evalValue(Context c, Context.Type type) + public Value evalValue(final Context c, final Context.Type type) { ILazyFunction.checkInterrupts(); try { return AbstractFunction.this.eval(getParams(c)); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw Expression.handleCodeException(cc, exc, e, t); } } - private List getParams(Context c) + + private List getParams(final Context c) { if (params == null) { @@ -202,18 +232,22 @@ public abstract class Fluff boolean leftAssoc; - AbstractLazyOperator(int precedence, boolean leftAssoc) { + AbstractLazyOperator(final int precedence, final boolean leftAssoc) + { + super(); this.precedence = precedence; this.leftAssoc = leftAssoc; } @Override - public int getPrecedence() { + public int getPrecedence() + { return precedence; } @Override - public boolean isLeftAssoc() { + public boolean isLeftAssoc() + { return leftAssoc; } @@ -222,28 +256,32 @@ public abstract class Fluff public abstract static class AbstractOperator extends AbstractLazyOperator implements IOperator { - AbstractOperator(int precedence, boolean leftAssoc) { + AbstractOperator(final int precedence, final boolean leftAssoc) + { super(precedence, leftAssoc); } + @Override - public boolean pure() { + public boolean pure() + { return true; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Tokenizer.Token t, final LazyValue v1, final LazyValue v2) + public LazyValue lazyEval(final Context cc, final Context.Type type, final Expression e, final Tokenizer.Token t, final LazyValue v1, final LazyValue v2) { return (c, typeIgnored) -> { try { return AbstractOperator.this.eval(v1.evalValue(c, Context.Type.NONE), v2.evalValue(c, Context.Type.NONE)); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw Expression.handleCodeException(cc, exc, e, t); } @@ -253,21 +291,25 @@ public abstract class Fluff public abstract static class AbstractUnaryOperator extends AbstractOperator { - AbstractUnaryOperator(int precedence, boolean leftAssoc) { + AbstractUnaryOperator(final int precedence, final boolean leftAssoc) + { super(precedence, leftAssoc); } + @Override - public boolean pure() { + public boolean pure() + { return true; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public LazyValue lazyEval(Context cc, Context.Type type, Expression e, Tokenizer.Token t, final LazyValue v1, final LazyValue v2) + public LazyValue lazyEval(final Context cc, final Context.Type type, final Expression e, final Tokenizer.Token t, final LazyValue v1, final LazyValue v2) { if (v2 != null) { @@ -278,7 +320,7 @@ public abstract class Fluff { return AbstractUnaryOperator.this.evalUnary(v1.evalValue(c, Context.Type.NONE)); } - catch (RuntimeException exc) + catch (final RuntimeException exc) { throw Expression.handleCodeException(cc, exc, e, t); } @@ -286,7 +328,7 @@ public abstract class Fluff } @Override - public Value eval(Value v1, Value v2) + public Value eval(final Value v1, final Value v2) { throw new IllegalStateException("Shouldn't end up here"); } diff --git a/src/main/java/carpet/script/LazyValue.java b/src/main/java/carpet/script/LazyValue.java index 6f0fc15b..88713d08 100644 --- a/src/main/java/carpet/script/LazyValue.java +++ b/src/main/java/carpet/script/LazyValue.java @@ -2,7 +2,9 @@ package carpet.script; import carpet.script.value.Value; -/** LazyNumber interface created for lazily evaluated functions */ +/** + * LazyNumber interface created for lazily evaluated functions + */ @FunctionalInterface public interface LazyValue { @@ -11,13 +13,15 @@ public interface LazyValue LazyValue NULL = (c, t) -> Value.NULL; LazyValue ZERO = (c, t) -> Value.ZERO; - public static LazyValue ofConstant(Value val) { + static LazyValue ofConstant(final Value val) + { return new Constant(val); } Value evalValue(Context c, Context.Type type); - default Value evalValue(Context c){ + default Value evalValue(final Context c) + { return evalValue(c, Context.Type.NONE); } @@ -28,7 +32,8 @@ public interface LazyValue Value evalType(Context.Type type); @Override - default Value evalValue(Context c, Context.Type type) { + default Value evalValue(final Context c, final Context.Type type) + { return evalType(type); } } @@ -38,21 +43,26 @@ public interface LazyValue { Value result; - public Constant(Value value) + public Constant(final Value value) { result = value; } - public Value get() {return result;} + public Value get() + { + return result; + } @Override - public Value evalType(Context.Type type) { + public Value evalType(final Context.Type type) + { return result.fromConstant(); } @Override - public Value evalValue(Context c, Context.Type type) { + public Value evalValue(final Context c, final Context.Type type) + { return result.fromConstant(); } } diff --git a/src/main/java/carpet/script/Module.java b/src/main/java/carpet/script/Module.java index 8bf86754..b687c073 100644 --- a/src/main/java/carpet/script/Module.java +++ b/src/main/java/carpet/script/Module.java @@ -14,23 +14,24 @@ import carpet.script.argument.FileArgument; import net.minecraft.nbt.Tag; import net.minecraft.world.level.storage.LevelResource; -public record Module(String name, String code, boolean library) { +public record Module(String name, String code, boolean library) +{ public Module { Objects.requireNonNull(name); Objects.requireNonNull(code); } - public static Module fromPath(Path path) + public static Module fromPath(final Path path) { - boolean library = path.getFileName().toString().endsWith(".scl"); + final boolean library = path.getFileName().toString().endsWith(".scl"); try { - String name = path.getFileName().toString().replaceFirst("\\.scl?","").toLowerCase(Locale.ROOT); - String code = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); + final String name = path.getFileName().toString().replaceFirst("\\.scl?", "").toLowerCase(Locale.ROOT); + final String code = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); return new Module(name, code, library); } - catch (IOException e) + catch (final IOException e) { throw new IllegalArgumentException("Failed to load scarpet module", e); } @@ -38,79 +39,96 @@ public record Module(String name, String code, boolean library) { /** * Creates a new {@link Module} with an app located in Carpet's JAR. + * * @param scriptName A {@link String} being the name of the script. The extension will be autocompleted - * @param isLibrary A {@link boolean} indicating whether or not the script is a library + * @param isLibrary A {@link boolean} indicating whether or not the script is a library * @return The created {@link BundledModule} */ - public static Module carpetNative(String scriptName, boolean isLibrary) + public static Module carpetNative(final String scriptName, final boolean isLibrary) { return fromJarPath("assets/carpet/scripts/", scriptName, isLibrary); } - + /** * Creates a new {@link Module} with an app located at a specified path inside some mod's JAR. - * @see #fromJarPathWithCustomName(String, String, boolean) - * - * @param path A {@link String} being the path to the directory where the app is located. + * + * @param path A {@link String} being the path to the directory where the app is located. * @param scriptName A {@link String} being the name of the script. The extension will be autocompleted - * @param isLibrary A {@link boolean} indicating whether or not the script is a library + * @param isLibrary A {@link boolean} indicating whether or not the script is a library * @return The created {@link BundledModule} + * @see #fromJarPathWithCustomName(String, String, boolean) */ - public static Module fromJarPath(String path, String scriptName, boolean isLibrary) { - return fromJarPathWithCustomName(path + scriptName + (isLibrary ? ".scl":".sc"), scriptName, isLibrary); + public static Module fromJarPath(final String path, final String scriptName, final boolean isLibrary) + { + return fromJarPathWithCustomName(path + scriptName + (isLibrary ? ".scl" : ".sc"), scriptName, isLibrary); } - + /** * Creates a new {@link Module} with an app located at the specified fullPath (inside a mod jar)with a custom name. - * @see #fromJarPath(String, String, boolean) - * - * @param fullPath A {@link String} being the full path to the app's code, including file and extension. + * + * @param fullPath A {@link String} being the full path to the app's code, including file and extension. * @param customName A {@link String} being the custom name for the script. - * @param isLibrary A {@link boolean} indicating whether or not the script is a library + * @param isLibrary A {@link boolean} indicating whether or not the script is a library * @return The created {@link Module} + * @see #fromJarPath(String, String, boolean) */ - public static Module fromJarPathWithCustomName(String fullPath, String customName, boolean isLibrary) { + public static Module fromJarPathWithCustomName(final String fullPath, final String customName, final boolean isLibrary) + { try { - String name = customName.toLowerCase(Locale.ROOT); - String code = IOUtils.toString( + final String name = customName.toLowerCase(Locale.ROOT); + final String code = IOUtils.toString( Module.class.getClassLoader().getResourceAsStream(fullPath), StandardCharsets.UTF_8 ); return new Module(name, code, isLibrary); } - catch (IOException e) + catch (final IOException e) { throw new IllegalArgumentException("Failed to load bundled module", e); } } - - public static Tag getData(Module module) + + public static Tag getData(final Module module) { - Path dataFile = resolveResource(module); - if (dataFile == null) return null; - if (!Files.exists(dataFile) || !(Files.isRegularFile(dataFile))) return null; - synchronized (FileArgument.writeIOSync) { return FileArgument.readTag(dataFile); } + final Path dataFile = resolveResource(module); + if (dataFile == null || !Files.exists(dataFile) || !(Files.isRegularFile(dataFile))) + { + return null; + } + synchronized (FileArgument.writeIOSync) + { + return FileArgument.readTag(dataFile); + } } - public static void saveData(Module module, Tag globalState) + public static void saveData(final Module module, final Tag globalState) { - Path dataFile = resolveResource(module); - if (dataFile == null) return; - if (!Files.exists(dataFile.getParent())) { - try { + final Path dataFile = resolveResource(module); + if (dataFile == null) + { + return; + } + if (!Files.exists(dataFile.getParent())) + { + try + { Files.createDirectories(dataFile.getParent()); - } catch (IOException e) { + } + catch (final IOException e) + { throw new IllegalStateException(e); } } - synchronized (FileArgument.writeIOSync) { FileArgument.writeTagDisk(globalState, dataFile, false); } + synchronized (FileArgument.writeIOSync) + { + FileArgument.writeTagDisk(globalState, dataFile, false); + } } - private static Path resolveResource(Module module) + private static Path resolveResource(final Module module) { - if (module == null) return null; // commandline app - return CarpetServer.minecraft_server.getWorldPath(LevelResource.ROOT).resolve("scripts/"+module.name()+".data.nbt"); + return module == null ? null : CarpetServer.minecraft_server.getWorldPath(LevelResource.ROOT).resolve("scripts/" + module.name() + ".data.nbt"); // commandline app } } diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java index a8eb3e85..6737be00 100644 --- a/src/main/java/carpet/script/ScriptHost.java +++ b/src/main/java/carpet/script/ScriptHost.java @@ -38,41 +38,45 @@ public abstract class ScriptHost private final Set deprecations = new HashSet<>(); - public Random getRandom(long aLong) + public Random getRandom(final long aLong) { if (randomizers.size() > 65536) + { randomizers.clear(); + } return randomizers.computeIfAbsent(aLong, Random::new); } - public boolean resetRandom(long aLong) { + public boolean resetRandom(final long aLong) + { return randomizers.remove(aLong) != null; } public static class ModuleData { Module parent; - public Map globalFunctions = new Object2ObjectOpenHashMap<>(); - public Map globalVariables = new Object2ObjectOpenHashMap<>(); - public Map functionImports = new Object2ObjectOpenHashMap<>(); // imported functions string to module - public Map globalsImports = new Object2ObjectOpenHashMap<>(); // imported global variables string to module - public Map futureImports = new Object2ObjectOpenHashMap<>(); // imports not known before used + public final Map globalFunctions = new Object2ObjectOpenHashMap<>(); + public final Map globalVariables = new Object2ObjectOpenHashMap<>(); + public final Map functionImports = new Object2ObjectOpenHashMap<>(); // imported functions string to module + public final Map globalsImports = new Object2ObjectOpenHashMap<>(); // imported global variables string to module + public final Map futureImports = new Object2ObjectOpenHashMap<>(); // imports not known before used - public ModuleData(Module parent, ModuleData other) + public ModuleData(final Module parent, final ModuleData other) { + super(); // imports are just pointers, but they still point to the wrong modules (point to the parent) this.parent = parent; globalFunctions.putAll(other.globalFunctions); other.globalVariables.forEach((key, value) -> { - Value var = value.evalValue(null); - Value copy = var.deepcopy(); + final Value var = value.evalValue(null); + final Value copy = var.deepcopy(); copy.boundVariable = var.boundVariable; globalVariables.put(key, (c, t) -> copy); }); } - public void setImportsBasedOn(ScriptHost host, ModuleData other) + public void setImportsBasedOn(final ScriptHost host, final ModuleData other) { // fixing imports other.functionImports.forEach((name, targetData) -> { @@ -87,20 +91,24 @@ public abstract class ScriptHost } - public ModuleData(Module parent) + public ModuleData(final Module parent) { this.parent = parent; } } + protected final Map userHosts = new Object2ObjectOpenHashMap<>(); - private Map moduleData = new HashMap<>(); // marking imports - private Map modules = new HashMap<>(); + private final Map moduleData = new HashMap<>(); // marking imports + private final Map modules = new HashMap<>(); protected ScriptHost parent; protected boolean perUser; public String user; - public String getName() {return main ==null?null: main.name();} + public String getName() + { + return main == null ? null : main.name(); + } public final Module main; @@ -109,9 +117,10 @@ public abstract class ScriptHost { List apply(Expression expression, Tokenizer.Token token, Context context, String message); } + public ErrorSnooper errorSnooper = null; - protected ScriptHost(Module code, ScriptServer scriptServer, boolean perUser, ScriptHost parent) + protected ScriptHost(final Module code, final ScriptServer scriptServer, final boolean perUser, final ScriptHost parent) { this.parent = parent; this.main = code; @@ -119,24 +128,30 @@ public abstract class ScriptHost this.user = null; this.strict = false; this.scriptServer = scriptServer; - ModuleData moduleData = new ModuleData(code); + final ModuleData moduleData = new ModuleData(code); initializeModuleGlobals(moduleData); this.moduleData.put(code, moduleData); - this.modules.put(code==null?null:code.name(), code); + this.modules.put(code == null ? null : code.name(), code); mainThread = Thread.currentThread(); } - void initializeModuleGlobals(ModuleData md) + void initializeModuleGlobals(final ModuleData md) { } - public void importModule(Context c, String moduleName) + public void importModule(final Context c, final String moduleName) { - if (modules.containsKey(moduleName.toLowerCase(Locale.ROOT))) return; // aready imported - Module module = getModuleOrLibraryByName(moduleName); - if (modules.containsKey(module.name())) return; // aready imported, once again, in case some discrepancies in names? + if (modules.containsKey(moduleName.toLowerCase(Locale.ROOT))) + { + return; // aready imported + } + final Module module = getModuleOrLibraryByName(moduleName); + if (modules.containsKey(module.name())) + { + return; // aready imported, once again, in case some discrepancies in names? + } modules.put(module.name(), module); - ModuleData data = new ModuleData(module); + final ModuleData data = new ModuleData(module); initializeModuleGlobals(data); moduleData.put(module, data); runModuleCode(c, module); @@ -144,20 +159,21 @@ public abstract class ScriptHost //modules.remove(module.getName()); //throw new InternalExpressionException("Failed to import a module "+moduleName); } - public void importNames(Context c, Module targetModule, String sourceModuleName, List identifiers ) + + public void importNames(final Context c, final Module targetModule, final String sourceModuleName, final List identifiers) { if (!moduleData.containsKey(targetModule)) { throw new InternalExpressionException("Cannot import to module that doesn't exist"); } - Module source = modules.get(sourceModuleName); - ModuleData sourceData = moduleData.get(source); - ModuleData targetData = moduleData.get(targetModule); + final Module source = modules.get(sourceModuleName); + final ModuleData sourceData = moduleData.get(source); + final ModuleData targetData = moduleData.get(targetModule); if (sourceData == null || targetData == null) { throw new InternalExpressionException("Cannot import from module that is not imported"); } - for (String identifier: identifiers) + for (final String identifier : identifiers) { if (sourceData.globalFunctions.containsKey(identifier)) { @@ -174,10 +190,10 @@ public abstract class ScriptHost } } - public Stream availableImports(String moduleName) + public Stream availableImports(final String moduleName) { - Module source = modules.get(moduleName); - ModuleData sourceData = moduleData.get(source); + final Module source = modules.get(moduleName); + final ModuleData sourceData = moduleData.get(source); if (sourceData == null) { throw new InternalExpressionException("Cannot import from module that is not imported"); @@ -192,136 +208,195 @@ public abstract class ScriptHost protected abstract void runModuleCode(Context c, Module module); // this should be shell out in the executor - public FunctionValue getFunction(String name) { return getFunction(main, name); } - public FunctionValue getAssertFunction(Module module, String name) + public FunctionValue getFunction(final String name) { - FunctionValue ret = getFunction(module, name); + return getFunction(main, name); + } + + public FunctionValue getAssertFunction(final Module module, final String name) + { + final FunctionValue ret = getFunction(module, name); if (ret == null) { if (module == main) - throw new InternalExpressionException("Function '"+name+"' is not defined yet"); + { + throw new InternalExpressionException("Function '" + name + "' is not defined yet"); + } else - throw new InternalExpressionException("Function '"+name+"' is not defined nor visible by its name in the imported module '"+module.name()+"'"); + { + throw new InternalExpressionException("Function '" + name + "' is not defined nor visible by its name in the imported module '" + module.name() + "'"); + } } return ret; } - private FunctionValue getFunction(Module module, String name) + + private FunctionValue getFunction(final Module module, final String name) { - ModuleData local = getModuleData(module); + final ModuleData local = getModuleData(module); FunctionValue ret = local.globalFunctions.get(name); // most uses would be from local scope anyways - if (ret != null) return ret; + if (ret != null) + { + return ret; + } ModuleData target = local.functionImports.get(name); if (target != null) { ret = target.globalFunctions.get(name); - if (ret != null) return ret; + if (ret != null) + { + return ret; + } } // not in local scope - will need to travel over import links target = local.futureImports.get(name); - if (target == null) return null; + if (target == null) + { + return null; + } target = findModuleDataFromFunctionImports(name, target, 0); - if (target == null) return null; + if (target == null) + { + return null; + } local.futureImports.remove(name); local.functionImports.put(name, target); return target.globalFunctions.get(name); } - private ModuleData findModuleDataFromFunctionImports(String name, ModuleData source, int ttl) + private ModuleData findModuleDataFromFunctionImports(final String name, final ModuleData source, final int ttl) { - if (ttl > 64) throw new InternalExpressionException("Cannot import "+name+", either your imports are too deep or too loopy"); + if (ttl > 64) + { + throw new InternalExpressionException("Cannot import " + name + ", either your imports are too deep or too loopy"); + } if (source.globalFunctions.containsKey(name)) + { return source; + } if (source.functionImports.containsKey(name)) - return findModuleDataFromFunctionImports(name, source.functionImports.get(name), ttl+1); + { + return findModuleDataFromFunctionImports(name, source.functionImports.get(name), ttl + 1); + } if (source.futureImports.containsKey(name)) - return findModuleDataFromFunctionImports(name, source.futureImports.get(name), ttl+1); + { + return findModuleDataFromFunctionImports(name, source.futureImports.get(name), ttl + 1); + } return null; } - public LazyValue getGlobalVariable(String name) { return getGlobalVariable(main, name); } - public LazyValue getGlobalVariable(Module module, String name) + public LazyValue getGlobalVariable(final String name) { - ModuleData local = getModuleData(module); + return getGlobalVariable(main, name); + } + + public LazyValue getGlobalVariable(final Module module, final String name) + { + final ModuleData local = getModuleData(module); LazyValue ret = local.globalVariables.get(name); // most uses would be from local scope anyways - if (ret != null) return ret; + if (ret != null) + { + return ret; + } ModuleData target = local.globalsImports.get(name); if (target != null) { ret = target.globalVariables.get(name); - if (ret != null) return ret; + if (ret != null) + { + return ret; + } } // not in local scope - will need to travel over import links target = local.futureImports.get(name); - if (target == null) return null; + if (target == null) + { + return null; + } target = findModuleDataFromGlobalImports(name, target, 0); - if (target == null) return null; + if (target == null) + { + return null; + } local.futureImports.remove(name); local.globalsImports.put(name, target); return target.globalVariables.get(name); } - private ModuleData findModuleDataFromGlobalImports(String name, ModuleData source, int ttl) + private ModuleData findModuleDataFromGlobalImports(final String name, final ModuleData source, final int ttl) { - if (ttl > 64) throw new InternalExpressionException("Cannot import "+name+", either your imports are too deep or too loopy"); + if (ttl > 64) + { + throw new InternalExpressionException("Cannot import " + name + ", either your imports are too deep or too loopy"); + } if (source.globalVariables.containsKey(name)) + { return source; + } if (source.globalsImports.containsKey(name)) - return findModuleDataFromGlobalImports(name, source.globalsImports.get(name), ttl+1); + { + return findModuleDataFromGlobalImports(name, source.globalsImports.get(name), ttl + 1); + } if (source.futureImports.containsKey(name)) - return findModuleDataFromGlobalImports(name, source.futureImports.get(name), ttl+1); + { + return findModuleDataFromGlobalImports(name, source.futureImports.get(name), ttl + 1); + } return null; } - public void delFunctionWithPrefix(Module module, String prefix) + public void delFunctionWithPrefix(final Module module, final String prefix) { - ModuleData data = getModuleData(module); + final ModuleData data = getModuleData(module); data.globalFunctions.entrySet().removeIf(e -> e.getKey().startsWith(prefix)); data.functionImports.entrySet().removeIf(e -> e.getKey().startsWith(prefix)); } - public void delFunction(Module module, String funName) + + public void delFunction(final Module module, final String funName) { - ModuleData data = getModuleData(module); + final ModuleData data = getModuleData(module); data.globalFunctions.remove(funName); data.functionImports.remove(funName); } - public void delGlobalVariableWithPrefix(Module module, String prefix) + public void delGlobalVariableWithPrefix(final Module module, final String prefix) { - ModuleData data = getModuleData(module); + final ModuleData data = getModuleData(module); data.globalVariables.entrySet().removeIf(e -> e.getKey().startsWith(prefix)); data.globalsImports.entrySet().removeIf(e -> e.getKey().startsWith(prefix)); } - public void delGlobalVariable(Module module, String varName) + public void delGlobalVariable(final Module module, final String varName) { - ModuleData data = getModuleData(module); + final ModuleData data = getModuleData(module); data.globalFunctions.remove(varName); data.functionImports.remove(varName); } - private ModuleData getModuleData(Module module) + private ModuleData getModuleData(final Module module) { - ModuleData data = moduleData.get(module); - if (data == null) throw new IntegrityException("Module structure changed for the app. Did you reload the app with tasks running?"); + final ModuleData data = moduleData.get(module); + if (data == null) + { + throw new IntegrityException("Module structure changed for the app. Did you reload the app with tasks running?"); + } return data; } - protected void assertAppIntegrity(Module module) + protected void assertAppIntegrity(final Module module) { getModuleData(module); } - public void addUserDefinedFunction(Context ctx, Module module, String name, FunctionValue fun) + public void addUserDefinedFunction(final Context ctx, final Module module, final String name, final FunctionValue fun) { getModuleData(module).globalFunctions.put(name, fun); } - public void setGlobalVariable(Module module, String name, LazyValue lv) + public void setGlobalVariable(final Module module, final String name, final LazyValue lv) { getModuleData(module).globalVariables.put(name, lv); } - public Stream globalVariableNames(Module module, Predicate predicate) + public Stream globalVariableNames(final Module module, final Predicate predicate) { return Stream.concat(Stream.concat( getModuleData(module).globalVariables.keySet().stream(), @@ -329,27 +404,33 @@ public abstract class ScriptHost ), getModuleData(module).futureImports.keySet().stream().filter(s -> s.startsWith("global_"))).filter(predicate); } - public Stream globalFunctionNames(Module module, Predicate predicate) + public Stream globalFunctionNames(final Module module, final Predicate predicate) { return Stream.concat(Stream.concat( getModuleData(module).globalFunctions.keySet().stream(), getModuleData(module).functionImports.keySet().stream() - ),getModuleData(module).futureImports.keySet().stream().filter(s -> !s.startsWith("global_"))).filter(predicate); + ), getModuleData(module).futureImports.keySet().stream().filter(s -> !s.startsWith("global_"))).filter(predicate); } - public ScriptHost retrieveForExecution(String /*Nullable*/ user) + public ScriptHost retrieveForExecution(final String /*Nullable*/ user) { - if (!perUser) return this; - ScriptHost oldUserHost = userHosts.get(user); - if (oldUserHost != null) return oldUserHost; - ScriptHost userHost = this.duplicate(); + if (!perUser) + { + return this; + } + final ScriptHost oldUserHost = userHosts.get(user); + if (oldUserHost != null) + { + return oldUserHost; + } + final ScriptHost userHost = this.duplicate(); userHost.user = user; this.setupUserHost(userHost); userHosts.put(user, userHost); return userHost; } - protected void setupUserHost(ScriptHost host) + protected void setupUserHost(final ScriptHost host) { // adding imports host.modules.putAll(this.modules); @@ -358,57 +439,65 @@ public abstract class ScriptHost host.moduleData.forEach((module, data) -> data.setImportsBasedOn(host, this.moduleData.get(data.parent))); } - synchronized public void handleExpressionException(String msg, ExpressionException exc) + public synchronized void handleExpressionException(final String msg, final ExpressionException exc) { - System.out.println(msg+": "+exc); + System.out.println(msg + ": " + exc); } - protected abstract ScriptHost duplicate(); - public Object getLock(Value name) + public Object getLock(final Value name) { - return locks.computeIfAbsent(name, (n) -> new Object()); + return locks.computeIfAbsent(name, n -> new Object()); } - public ThreadPoolExecutor getExecutor(Value pool) + public ThreadPoolExecutor getExecutor(final Value pool) { - if (inTermination) return null; - return executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor) Executors.newCachedThreadPool()); + if (inTermination) + { + return null; + } + return executorServices.computeIfAbsent(pool, v -> (ThreadPoolExecutor) Executors.newCachedThreadPool()); } public int taskCount() { return executorServices.values().stream().map(ThreadPoolExecutor::getActiveCount).reduce(0, Integer::sum); } - public int taskCount(Value pool) + + public int taskCount(final Value pool) { - if (executorServices.containsKey(pool)) - { - return executorServices.get(pool).getActiveCount(); - } - return 0; + return executorServices.containsKey(pool) ? executorServices.get(pool).getActiveCount() : 0; } public void onClose() { inTermination = true; executorServices.values().forEach(ThreadPoolExecutor::shutdown); - for (ScriptHost uh : userHosts.values()) uh.onClose(); + for (final ScriptHost uh : userHosts.values()) + { + uh.onClose(); + } if (taskCount() > 0) { executorServices.values().forEach(e -> { - ExecutorService stopper = Executors.newSingleThreadExecutor(); - stopper.submit( () -> { - try { + final ExecutorService stopper = Executors.newSingleThreadExecutor(); + stopper.submit(() -> { + try + { // Wait a while for existing tasks to terminate - if (!e.awaitTermination(1500, TimeUnit.MILLISECONDS)) { + if (!e.awaitTermination(1500, TimeUnit.MILLISECONDS)) + { e.shutdownNow(); // Cancel currently executing tasks // Wait a while for tasks to respond to being cancelled if (!e.awaitTermination(1500, TimeUnit.MILLISECONDS)) + { CarpetScriptServer.LOG.error("Failed to stop app's thread"); + } } - } catch (InterruptedException ie) { + } + catch (final InterruptedException ie) + { // (Re-)Cancel if current thread also interrupted e.shutdownNow(); // Preserve interrupt status @@ -421,12 +510,15 @@ public abstract class ScriptHost } } - public void setPerPlayer(boolean isPerUser) + public void setPerPlayer(final boolean isPerUser) { perUser = isPerUser; } - public boolean isPerUser() {return perUser;} + public boolean isPerUser() + { + return perUser; + } public Set getUserList() { @@ -436,21 +528,24 @@ public abstract class ScriptHost public void resetErrorSnooper() { - errorSnooper=null; + errorSnooper = null; } public static final Logger DEPRECATION_LOG = LoggerFactory.getLogger("Scarpet Deprecation Warnings"); - public boolean issueDeprecation(String feature) + public boolean issueDeprecation(final String feature) { - if (deprecations.contains(feature)) return false; + if (deprecations.contains(feature)) + { + return false; + } deprecations.add(feature); - DEPRECATION_LOG.warn("'"+feature+"' is deprecated and soon will be removed. Please consult the docs for their replacement"); + DEPRECATION_LOG.warn("'" + feature + "' is deprecated and soon will be removed. Please consult the docs for their replacement"); return true; } - public ScriptServer scriptServer() - { - return scriptServer; - } + public ScriptServer scriptServer() + { + return scriptServer; + } } diff --git a/src/main/java/carpet/script/ScriptServer.java b/src/main/java/carpet/script/ScriptServer.java index 24e36383..5d13d024 100644 --- a/src/main/java/carpet/script/ScriptServer.java +++ b/src/main/java/carpet/script/ScriptServer.java @@ -6,6 +6,7 @@ import java.util.concurrent.ConcurrentHashMap; import carpet.script.value.Value; // WIP -public class ScriptServer { +public class ScriptServer +{ public final Map systemGlobals = new ConcurrentHashMap<>(); } diff --git a/src/main/java/carpet/script/Tokenizer.java b/src/main/java/carpet/script/Tokenizer.java index 645b53ad..e62d4394 100644 --- a/src/main/java/carpet/script/Tokenizer.java +++ b/src/main/java/carpet/script/Tokenizer.java @@ -16,25 +16,35 @@ import java.util.stream.StreamSupport; */ public class Tokenizer implements Iterator { - /** What character to use for decimal separators. */ + /** + * What character to use for decimal separators. + */ private static final char decimalSeparator = '.'; - /** What character to use for minus sign (negative values). */ + /** + * What character to use for minus sign (negative values). + */ private static final char minusSign = '-'; - /** Actual position in expression string. */ + /** + * Actual position in expression string. + */ private int pos = 0; private int lineno = 0; private int linepos = 0; - private boolean comments; - private boolean newLinesMarkers; - /** The original input expression. */ - private String input; - /** The previous token or null if none. */ + private final boolean comments; + private final boolean newLinesMarkers; + /** + * The original input expression. + */ + private final String input; + /** + * The previous token or null if none. + */ private Token previousToken; - private Expression expression; - private Context context; + private final Expression expression; + private final Context context; - Tokenizer(Context c, Expression expr, String input, boolean allowComments, boolean allowNewLineMakers) + Tokenizer(final Context c, final Expression expr, final String input, final boolean allowComments, final boolean allowNewLineMakers) { this.input = input; this.expression = expr; @@ -45,16 +55,18 @@ public class Tokenizer implements Iterator public List postProcess() { - Iterable iterable = () -> this; - List originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); - List cleanedTokens = new ArrayList<>(); + final Iterable iterable = () -> this; + final List originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); + final List cleanedTokens = new ArrayList<>(); Token last = null; - while (originalTokens.size() > 0) + while (!originalTokens.isEmpty()) { - Token current = originalTokens.remove(originalTokens.size()-1); + final Token current = originalTokens.remove(originalTokens.size() - 1); if (current.type == Token.TokenType.MARKER && current.surface.startsWith("//")) + { continue; - // skipping comments + } + // skipping comments if (!isSemicolon(current) || (last != null && last.type != Token.TokenType.CLOSE_PAREN && last.type != Token.TokenType.COMMA && !isSemicolon(last))) { @@ -84,7 +96,9 @@ public class Tokenizer implements Iterator cleanedTokens.add(current); } if (!(current.type == Token.TokenType.MARKER && current.surface.equals("$"))) + { last = current; + } } Collections.reverse(cleanedTokens); return cleanedTokens; @@ -106,30 +120,33 @@ public class Tokenizer implements Iterator return (pos < (input.length() - 1)) ? input.charAt(pos + 1) : 0; } - private boolean isHexDigit(char ch) + private boolean isHexDigit(final char ch) { return ch == 'x' || ch == 'X' || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); } - private static boolean isSemicolon(Token tok) + private static boolean isSemicolon(final Token tok) { - return ( tok.type == Token.TokenType.OPERATOR && tok.surface.equals(";") ) - || (tok.type == Token.TokenType.UNARY_OPERATOR && tok.surface.equals(";u") ); + return (tok.type == Token.TokenType.OPERATOR && tok.surface.equals(";")) + || (tok.type == Token.TokenType.UNARY_OPERATOR && tok.surface.equals(";u")); } - public static List simplepass(String input) + public static List simplepass(final String input) { - Tokenizer tok = new Tokenizer(null, null, input, false, false); - List res = new ArrayList<>(); - while (tok.hasNext()) res.add(tok.next()); + final Tokenizer tok = new Tokenizer(null, null, input, false, false); + final List res = new ArrayList<>(); + while (tok.hasNext()) + { + res.add(tok.next()); + } return res; } @Override public Token next() { - Token token = new Token(); + final Token token = new Token(); if (pos >= input.length()) { @@ -139,7 +156,7 @@ public class Tokenizer implements Iterator while (Character.isWhitespace(ch) && pos < input.length()) { linepos++; - if (ch=='\n') + if (ch == '\n') { lineno++; linepos = 0; @@ -153,10 +170,12 @@ public class Tokenizer implements Iterator boolean isHex = false; if (Character.isDigit(ch)) // || (ch == decimalSeparator && Character.isDigit(peekNextChar()))) - // decided to no support this notation to favour element access via . operator + // decided to no support this notation to favour element access via . operator { if (ch == '0' && (peekNextChar() == 'x' || peekNextChar() == 'X')) + { isHex = true; + } while ((isHex && isHexDigit( ch)) @@ -181,13 +200,15 @@ public class Tokenizer implements Iterator linepos++; token.type = Token.TokenType.STRINGPARAM; if (pos == input.length() && expression != null && context != null) + { throw new ExpressionException(context, this.expression, token, "Program truncated"); + } ch = input.charAt(pos); while (ch != '\'') { if (ch == '\\') { - char nextChar = peekNextChar(); + final char nextChar = peekNextChar(); if (nextChar == 'n') { token.append('\n'); @@ -213,22 +234,26 @@ public class Tokenizer implements Iterator pos--; linepos--; } - pos+=2; - linepos+=2; + pos += 2; + linepos += 2; if (pos == input.length() && expression != null && context != null) + { throw new ExpressionException(context, this.expression, token, "Program truncated"); + } } else { token.append(input.charAt(pos++)); linepos++; - if (ch=='\n') + if (ch == '\n') { lineno++; linepos = 0; } if (pos == input.length() && expression != null && context != null) + { throw new ExpressionException(context, this.expression, token, "Program truncated"); + } } ch = input.charAt(pos); } @@ -252,7 +277,7 @@ public class Tokenizer implements Iterator { ch = input.charAt(pos++); linepos++; - if (ch=='\n') + if (ch == '\n') { lineno++; linepos = 0; @@ -291,14 +316,16 @@ public class Tokenizer implements Iterator (ch == ')' || ch == ',' || ch == ']' || ch == '}') && !previousToken.surface.equalsIgnoreCase(";") ) + { throw new ExpressionException(context, this.expression, previousToken, "Can't have operator " + previousToken.surface + " at the end of a subexpression"); + } } else { String greedyMatch = ""; - int initialPos = pos; - int initialLinePos = linepos; + final int initialPos = pos; + final int initialLinePos = linepos; ch = input.charAt(pos); int validOperatorSeenUntil = -1; while (!Character.isLetter(ch) && !Character.isDigit(ch) && "_".indexOf(ch) < 0 @@ -309,13 +336,13 @@ public class Tokenizer implements Iterator if (comments && "//".equals(greedyMatch)) { - while ( ch != '\n' && pos < input.length()) + while (ch != '\n' && pos < input.length()) { ch = input.charAt(pos++); linepos++; greedyMatch += ch; } - if (ch=='\n') + if (ch == '\n') { lineno++; linepos = 0; @@ -344,7 +371,7 @@ public class Tokenizer implements Iterator { token.append(input.substring(initialPos, validOperatorSeenUntil)); pos = validOperatorSeenUntil; - linepos = initialLinePos+validOperatorSeenUntil-initialPos; + linepos = initialLinePos + validOperatorSeenUntil - initialPos; } else { @@ -353,7 +380,7 @@ public class Tokenizer implements Iterator if (previousToken == null || previousToken.type == Token.TokenType.OPERATOR || previousToken.type == Token.TokenType.OPEN_PAREN || previousToken.type == Token.TokenType.COMMA - || (previousToken.type == Token.TokenType.MARKER && ( previousToken.surface.equals("{") || previousToken.surface.equals("[") ) ) + || (previousToken.type == Token.TokenType.MARKER && (previousToken.surface.equals("{") || previousToken.surface.equals("["))) ) { token.surface += "u"; @@ -365,25 +392,25 @@ public class Tokenizer implements Iterator } } if (expression != null && context != null && previousToken != null && - ( - token.type == Token.TokenType.LITERAL || - token.type == Token.TokenType.HEX_LITERAL || - token.type == Token.TokenType.VARIABLE || - token.type == Token.TokenType.STRINGPARAM || - ( token.type == Token.TokenType.MARKER && ( previousToken.surface.equalsIgnoreCase("{") || previousToken.surface.equalsIgnoreCase("["))) || - token.type == Token.TokenType.FUNCTION - ) &&( + ( + token.type == Token.TokenType.LITERAL || + token.type == Token.TokenType.HEX_LITERAL || + token.type == Token.TokenType.VARIABLE || + token.type == Token.TokenType.STRINGPARAM || + (token.type == Token.TokenType.MARKER && (previousToken.surface.equalsIgnoreCase("{") || previousToken.surface.equalsIgnoreCase("["))) || + token.type == Token.TokenType.FUNCTION + ) && ( previousToken.type == Token.TokenType.VARIABLE || - previousToken.type == Token.TokenType.FUNCTION || - previousToken.type == Token.TokenType.LITERAL || - previousToken.type == Token.TokenType.CLOSE_PAREN || - ( previousToken.type == Token.TokenType.MARKER && ( previousToken.surface.equalsIgnoreCase("}") || previousToken.surface.equalsIgnoreCase("]"))) || - previousToken.type == Token.TokenType.HEX_LITERAL || - previousToken.type == Token.TokenType.STRINGPARAM - ) + previousToken.type == Token.TokenType.FUNCTION || + previousToken.type == Token.TokenType.LITERAL || + previousToken.type == Token.TokenType.CLOSE_PAREN || + (previousToken.type == Token.TokenType.MARKER && (previousToken.surface.equalsIgnoreCase("}") || previousToken.surface.equalsIgnoreCase("]"))) || + previousToken.type == Token.TokenType.HEX_LITERAL || + previousToken.type == Token.TokenType.STRINGPARAM + ) ) { - throw new ExpressionException(context, this.expression, previousToken, "'"+token.surface +"' is not allowed after '"+previousToken.surface+"'"); + throw new ExpressionException(context, this.expression, previousToken, "'" + token.surface + "' is not allowed after '" + previousToken.surface + "'"); } return previousToken = token; } @@ -403,10 +430,10 @@ public class Tokenizer implements Iterator LITERAL(false, true), HEX_LITERAL(false, true), STRINGPARAM(false, true), OPEN_PAREN(false, true), COMMA(false, true), CLOSE_PAREN(false, true), MARKER(false, true); - boolean functional; - boolean constant; + final boolean functional; + final boolean constant; - TokenType(boolean functional, boolean constant) + TokenType(final boolean functional, final boolean constant) { this.functional = functional; this.constant = constant; @@ -417,44 +444,47 @@ public class Tokenizer implements Iterator return functional; } - public boolean isConstant() { + public boolean isConstant() + { return constant; } } + public String surface = ""; public TokenType type; public int pos; public int linepos; public int lineno; public static final Token NONE = new Token(); - public Token morphedInto(TokenType newType, String newSurface) + + public Token morphedInto(final TokenType newType, final String newSurface) { - Token created = new Token(); + final Token created = new Token(); created.surface = newSurface; created.type = newType; created.pos = pos; created.linepos = linepos; - created.lineno= lineno; + created.lineno = lineno; return created; } - public void morph(TokenType type, String s) + public void morph(final TokenType type, final String s) { this.type = type; this.surface = s; } - public void append(char c) + public void append(final char c) { surface += c; } - public void append(String s) + public void append(final String s) { surface += s; } - public char charAt(int pos) + public char charAt(final int pos) { return surface.charAt(pos); } diff --git a/src/main/java/carpet/script/annotation/AnnotationParser.java b/src/main/java/carpet/script/annotation/AnnotationParser.java index 891c64a3..052cb524 100644 --- a/src/main/java/carpet/script/annotation/AnnotationParser.java +++ b/src/main/java/carpet/script/annotation/AnnotationParser.java @@ -105,32 +105,38 @@ public final class AnnotationParser * @see ScarpetFunction * @param clazz The class to parse */ - public static void parseFunctionClass(Class clazz) + public static void parseFunctionClass(final Class clazz) { // Only try to instantiate or require concrete classes if there are non-static annotated methods - Supplier instanceSupplier = Suppliers.memoize(() -> { + final Supplier instanceSupplier = Suppliers.memoize(() -> { if (Modifier.isAbstract(clazz.getModifiers())) + { throw new IllegalArgumentException("Function class must be concrete to support non-static methods! Class: " + clazz.getSimpleName()); + } try { return clazz.getConstructor().newInstance(); } - catch (ReflectiveOperationException e) + catch (final ReflectiveOperationException e) { throw new IllegalArgumentException( "Couldn't create instance of given " + clazz + ". This is needed for non-static methods. Make sure default constructor is available", e); } }); - Method[] methodz = clazz.getDeclaredMethods(); - for (Method method : methodz) + final Method[] methodz = clazz.getDeclaredMethods(); + for (final Method method : methodz) { if (!method.isAnnotationPresent(ScarpetFunction.class)) + { continue; + } if (method.getExceptionTypes().length != 0) + { throw new IllegalArgumentException("Annotated method '" + method.getName() +"', provided in '"+clazz+"' must not declare checked exceptions"); + } - ParsedFunction function = new ParsedFunction(method, clazz, instanceSupplier); + final ParsedFunction function = new ParsedFunction(method, clazz, instanceSupplier); functionList.add(function); } } @@ -141,10 +147,12 @@ public final class AnnotationParser * * @param expr The expression to add every function to */ - public static void apply(Expression expr) + public static void apply(final Expression expr) { - for (ParsedFunction function : functionList) + for (final ParsedFunction function : functionList) + { expr.addLazyFunction(function.name, function.scarpetParamCount, function); + } } private static class ParsedFunction implements TriFunction, LazyValue>, UsageProvider @@ -164,25 +172,27 @@ public final class AnnotationParser private final int scarpetParamCount; private final Context.Type contextType; - private ParsedFunction(Method method, Class originClass, Supplier instance) + private ParsedFunction(final Method method, final Class originClass, final Supplier instance) { this.name = method.getName(); this.isMethodVarArgs = method.isVarArgs(); this.methodParamCount = method.getParameterCount(); - Parameter[] methodParameters = method.getParameters(); + final Parameter[] methodParameters = method.getParameters(); this.valueConverters = new ValueConverter[isMethodVarArgs ? methodParamCount - 1 : methodParamCount]; for (int i = 0; i < this.methodParamCount; i++) { - Parameter param = methodParameters[i]; + final Parameter param = methodParameters[i]; if (!isMethodVarArgs || i != this.methodParamCount - 1) // Varargs converter is separate + { this.valueConverters[i] = ValueConverter.fromAnnotatedType(param.getAnnotatedType()); + } } - Class originalVarArgsType = isMethodVarArgs ? methodParameters[methodParamCount - 1].getType().getComponentType() : null; + final Class originalVarArgsType = isMethodVarArgs ? methodParameters[methodParamCount - 1].getType().getComponentType() : null; this.varArgsType = ClassUtils.primitiveToWrapper(originalVarArgsType); // Primitive array cannot be cast to Obj[] this.primitiveVarArgs = originalVarArgsType != null && originalVarArgsType.isPrimitive(); this.varArgsConverter = isMethodVarArgs ? ValueConverter.fromAnnotatedType(methodParameters[methodParamCount - 1].getAnnotatedType()) : null; - @SuppressWarnings("unchecked") // Yes. Making a T is not worth + @SuppressWarnings("unchecked") final // Yes. Making a T is not worth OutputConverter converter = OutputConverter.get((Class) method.getReturnType()); this.outputConverter = converter; @@ -193,13 +203,19 @@ public final class AnnotationParser { maxParams = method.getAnnotation(ScarpetFunction.class).maxParams(); if (maxParams == UNDEFINED_PARAMS) + { throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use ScarpetFunction.UNLIMITED_PARAMS for unlimited. " + "Provided in " + originClass); + } if (maxParams == ScarpetFunction.UNLIMITED_PARAMS) + { maxParams = Integer.MAX_VALUE; + } if (maxParams < this.minParams) + { throw new IllegalArgumentException("Provided maximum number of params for " + name + " is smaller than method's param count." + "Provided in " + originClass); + } } this.maxParams = maxParams; @@ -227,56 +243,66 @@ public final class AnnotationParser } @Override - public LazyValue apply(Context context, Context.Type t, List lazyValues) + public LazyValue apply(final Context context, final Context.Type t, final List lazyValues) { - List lv = AbstractLazyFunction.unpackLazy(lazyValues, context, contextType); + final List lv = AbstractLazyFunction.unpackLazy(lazyValues, context, contextType); if (isEffectivelyVarArgs) { if (lv.size() < minParams) - throw new InternalExpressionException("Function '" + name + "' expected at least " + minParams + " arguments, got " + lv.size() + ". " + { + throw new InternalExpressionException("Function '" + name + "' expected at least " + minParams + " arguments, got " + lv.size() + ". " + getUsage()); + } if (lv.size() > maxParams) - throw new InternalExpressionException("Function '" + name + " expected up to " + maxParams + " arguments, got " + lv.size() + ". " + { + throw new InternalExpressionException("Function '" + name + " expected up to " + maxParams + " arguments, got " + lv.size() + ". " + getUsage()); + } } - Object[] params = getMethodParams(lv, context, t); + final Object[] params = getMethodParams(lv, context, t); try { return outputConverter.convert(handle.invokeExact(params)); } - catch (Throwable e) + catch (final Throwable e) { - if (e instanceof RuntimeException) - throw (RuntimeException) e; + if (e instanceof RuntimeException re) + { + throw re; + } throw (Error) e; // Stack overflow or something. Methods are guaranteed not to throw checked exceptions } } // Hot code: Must be optimized - private Object[] getMethodParams(final List lv, final Context context, Context.Type theLazyT) + private Object[] getMethodParams(final List lv, final Context context, final Context.Type theLazyT) { - Object[] params = new Object[methodParamCount]; - ListIterator lvIterator = lv.listIterator(); + final Object[] params = new Object[methodParamCount]; + final ListIterator lvIterator = lv.listIterator(); - int regularArgs = isMethodVarArgs ? methodParamCount - 1 : methodParamCount; + final int regularArgs = isMethodVarArgs ? methodParamCount - 1 : methodParamCount; for (int i = 0; i < regularArgs; i++) { params[i] = valueConverters[i].checkAndConvert(lvIterator, context, theLazyT); if (params[i] == null) + { throw new InternalExpressionException("Incorrect argument passsed to '" + name + "' function.\n" + getUsage()); + } } if (isMethodVarArgs) { - int remaining = lv.size() - lvIterator.nextIndex(); - Object[] varArgs; + final int remaining = lv.size() - lvIterator.nextIndex(); + final Object[] varArgs; if (varArgsConverter.consumesVariableArgs()) { - List varArgsList = new ArrayList<>(); // fastutil's is extremely slow in toArray, and we use that + final List varArgsList = new ArrayList<>(); // fastutil's is extremely slow in toArray, and we use that while (lvIterator.hasNext()) { - Object obj = varArgsConverter.checkAndConvert(lvIterator, context, theLazyT); + final Object obj = varArgsConverter.checkAndConvert(lvIterator, context, theLazyT); if (obj == null) + { throw new InternalExpressionException("Incorrect argument passsed to '" + name + "' function.\n" + getUsage()); + } varArgsList.add(obj); } varArgs = varArgsList.toArray((Object[])Array.newInstance(varArgsType, 0)); @@ -287,7 +313,9 @@ public final class AnnotationParser { varArgs[i] = varArgsConverter.checkAndConvert(lvIterator, context, theLazyT); if (varArgs[i] == null) + { throw new InternalExpressionException("Incorrect argument passsed to '" + name + "' function.\n" + getUsage()); + } } } params[methodParamCount - 1] = primitiveVarArgs ? ArrayUtils.toPrimitive(varArgs) : varArgs; // Copies the array @@ -299,7 +327,7 @@ public final class AnnotationParser public String getUsage() { // Possibility: More descriptive messages using param.getName()? Would need changing gradle setup to keep those - StringBuilder builder = new StringBuilder("Usage: '"); + final StringBuilder builder = new StringBuilder("Usage: '"); builder.append(name); builder.append('('); builder.append(Arrays.stream(valueConverters).map(ValueConverter::getTypeName).filter(Objects::nonNull).collect(Collectors.joining(", "))); diff --git a/src/main/java/carpet/script/annotation/ListConverter.java b/src/main/java/carpet/script/annotation/ListConverter.java index 5abf88ff..abdfbc5b 100644 --- a/src/main/java/carpet/script/annotation/ListConverter.java +++ b/src/main/java/carpet/script/annotation/ListConverter.java @@ -32,34 +32,38 @@ final class ListConverter implements ValueConverter> } @Override - public List convert(Value value) + public List convert(final Value value) { return value instanceof ListValue ? convertListValue((ListValue) value) : allowSingletonCreation ? convertSingleton(value) : null; } - private List convertListValue(ListValue values) + private List convertListValue(final ListValue values) { - List list = new ArrayList<>(values.getItems().size()); - for (Value value : values) + final List list = new ArrayList<>(values.getItems().size()); + for (final Value value : values) { - T converted = itemConverter.convert(value); + final T converted = itemConverter.convert(value); if (converted == null) + { return null; + } list.add(converted); } return list; } - private List convertSingleton(Value val) + private List convertSingleton(final Value val) { - T converted = itemConverter.convert(val); + final T converted = itemConverter.convert(val); if (converted == null) + { return null; + } return Collections.singletonList(converted); } - private ListConverter(AnnotatedType itemType, boolean allowSingletonCreation) + private ListConverter(final AnnotatedType itemType, final boolean allowSingletonCreation) { itemConverter = ValueConverter.fromAnnotatedType(itemType); this.allowSingletonCreation = allowSingletonCreation; @@ -79,11 +83,11 @@ final class ListConverter implements ValueConverter> * @param annotatedType The type to get generics information from * @return A new {@link ListConverter} for the data specified in the {@link AnnotatedType} */ - static ListConverter fromAnnotatedType(AnnotatedType annotatedType) + static ListConverter fromAnnotatedType(final AnnotatedType annotatedType) { - AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType; - AnnotatedType itemType = paramType.getAnnotatedActualTypeArguments()[0]; - boolean allowSingletonCreation = annotatedType.isAnnotationPresent(Param.AllowSingleton.class); + final AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType; + final AnnotatedType itemType = paramType.getAnnotatedActualTypeArguments()[0]; + final boolean allowSingletonCreation = annotatedType.isAnnotationPresent(Param.AllowSingleton.class); return new ListConverter<>(itemType, allowSingletonCreation); } diff --git a/src/main/java/carpet/script/annotation/Locator.java b/src/main/java/carpet/script/annotation/Locator.java index 3f195607..0c447c3e 100644 --- a/src/main/java/carpet/script/annotation/Locator.java +++ b/src/main/java/carpet/script/annotation/Locator.java @@ -37,7 +37,7 @@ public interface Locator @Documented @Retention(RUNTIME) @Target({ PARAMETER, TYPE_USE }) - public @interface Block + @interface Block { /** *

Whether or not should the locator accept a single {@link String} as the parameter and let parsing to {@link BlockValue}.

@@ -66,7 +66,7 @@ public interface Locator @Documented @Retention(RUNTIME) @Target({ PARAMETER, TYPE_USE }) - public @interface Vec3d + @interface Vec3d { /** *

Whether or not should the {@link Vector3Argument} locator accept an optional direction aside from the @@ -94,7 +94,7 @@ public interface Locator @Documented @Retention(RUNTIME) @Target({ PARAMETER, TYPE_USE }) - public @interface Function + @interface Function { /** *

Whether this Locator should allow no function to be passed.

This is not compatible with {@link FunctionValue} type, since a @@ -115,18 +115,27 @@ public interface Locator * *

Not part of the public API, just that interfaces must have all members public

*/ - static final class Locators + final class Locators { - private Locators() {} + private Locators() + { + super(); + } - static ValueConverter fromAnnotatedType(AnnotatedType annoType, Class type) + static ValueConverter fromAnnotatedType(final AnnotatedType annoType, final Class type) { if (annoType.isAnnotationPresent(Block.class)) - return new BlockLocator(annoType.getAnnotation(Block.class), type); + { + return new BlockLocator<>(annoType.getAnnotation(Block.class), type); + } if (annoType.isAnnotationPresent(Function.class)) - return new FunctionLocator(annoType.getAnnotation(Function.class), type); + { + return new FunctionLocator<>(annoType.getAnnotation(Function.class), type); + } if (annoType.isAnnotationPresent(Vec3d.class)) - return new Vec3dLocator(annoType.getAnnotation(Vec3d.class), type); + { + return new Vec3dLocator<>(annoType.getAnnotation(Vec3d.class), type); + } throw new IllegalStateException("Locator#fromAnnotatedType got called with an incompatible AnnotatedType"); } @@ -137,28 +146,42 @@ public interface Locator private final boolean anyString; private final boolean optional; - public BlockLocator(Block annotation, Class type) + public BlockLocator(final Block annotation, final Class type) { + super(); this.acceptString = annotation.acceptString(); this.anyString = annotation.anyString(); this.optional = annotation.optional(); if (type != BlockArgument.class && (anyString || optional)) + { throw new IllegalArgumentException("Can only use anyString or optional parameters of Locator.Block if targeting a BlockArgument"); + } this.returnFunction = getReturnFunction(type); if (returnFunction == null) + { throw new IllegalArgumentException("Locator.Block can only be used against BlockArgument, BlockValue, BlockPos or BlockState types!"); + } } @SuppressWarnings("unchecked") - private static java.util.function.Function getReturnFunction(Class type) { + private static java.util.function.Function getReturnFunction(final Class type) + { if (type == BlockArgument.class) + { return r -> (R) r; + } if (type == BlockValue.class) + { return r -> (R) r.block; + } if (type == BlockPos.class) + { return r -> (R) r.block.getPos(); + } if (type == BlockState.class) + { return r -> (R) r.block.getBlockState(); + } return null; } @@ -169,9 +192,9 @@ public interface Locator } @Override - public R checkAndConvert(Iterator valueIterator, Context context, Context.Type theLazyT) + public R checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type theLazyT) { - BlockArgument locator = BlockArgument.findIn((CarpetContext) context, valueIterator, 0, acceptString, optional, anyString); + final BlockArgument locator = BlockArgument.findIn((CarpetContext) context, valueIterator, 0, acceptString, optional, anyString); return returnFunction.apply(locator); } } @@ -182,15 +205,19 @@ public interface Locator private final boolean optionalEntity; private final boolean returnVec3d; - public Vec3dLocator(Vec3d annotation, Class type) + public Vec3dLocator(final Vec3d annotation, final Class type) { this.optionalDirection = annotation.optionalDirection(); this.optionalEntity = annotation.optionalEntity(); this.returnVec3d = type == net.minecraft.world.phys.Vec3.class; // Because of the locator if (returnVec3d && optionalDirection) + { throw new IllegalArgumentException("optionalDirection Locator.Vec3d cannot be used for Vec3d type, use Vector3Argument instead"); + } if (!returnVec3d && type != Vector3Argument.class) + { throw new IllegalArgumentException("Locator.Vec3d can only be used in Vector3Argument or Vec3d types"); + } } @Override @@ -200,11 +227,10 @@ public interface Locator } @Override - public R checkAndConvert(Iterator valueIterator, Context context, Context.Type theLazyT) + public R checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type theLazyT) { - Vector3Argument locator = Vector3Argument.findIn(valueIterator, 0, optionalDirection, optionalEntity); - @SuppressWarnings("unchecked") - R ret = (R) (returnVec3d ? locator.vec : locator); + final Vector3Argument locator = Vector3Argument.findIn(valueIterator, 0, optionalDirection, optionalEntity); + @SuppressWarnings("unchecked") final R ret = (R) (returnVec3d ? locator.vec : locator); return ret; } } @@ -215,24 +241,28 @@ public interface Locator private final boolean allowNone; private final boolean checkArgs; - FunctionLocator(Function annotation, Class type) + FunctionLocator(final Function annotation, final Class type) { + super(); this.returnFunctionValue = type == FunctionValue.class; if (!returnFunctionValue && type != FunctionArgument.class) + { throw new IllegalArgumentException("Params annotated with Locator.Function must be of either FunctionArgument or FunctionValue type"); + } this.allowNone = annotation.allowNone(); this.checkArgs = annotation.checkArgs(); if (returnFunctionValue && allowNone) + { throw new IllegalArgumentException("Cannot use allowNone of Locator.Function in FunctionValue types, use FunctionArgument"); + } } @Override - public R checkAndConvert(Iterator valueIterator, Context context, Context.Type theLazyT) + public R checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type theLazyT) { - Module module = context.host.main; - FunctionArgument locator = FunctionArgument.findIn(context, module, Lists.newArrayList(valueIterator), 0, allowNone, checkArgs); - @SuppressWarnings("unchecked") - R ret = (R) (returnFunctionValue ? locator.function : locator); + final Module module = context.host.main; + final FunctionArgument locator = FunctionArgument.findIn(context, module, Lists.newArrayList(valueIterator), 0, allowNone, checkArgs); + @SuppressWarnings("unchecked") final R ret = (R) (returnFunctionValue ? locator.function : locator); return ret; } @@ -243,10 +273,10 @@ public interface Locator } } - private static abstract class AbstractLocator implements ValueConverter, Locator + private abstract static class AbstractLocator implements ValueConverter, Locator { @Override - public R convert(Value value) + public R convert(final Value value) { throw new UnsupportedOperationException("Cannot call a locator in a parameter that doesn't contain a context!"); } diff --git a/src/main/java/carpet/script/annotation/MapConverter.java b/src/main/java/carpet/script/annotation/MapConverter.java index fd26d30f..a39671f5 100644 --- a/src/main/java/carpet/script/annotation/MapConverter.java +++ b/src/main/java/carpet/script/annotation/MapConverter.java @@ -37,17 +37,19 @@ class MapConverter implements ValueConverter> } @Override - public Map convert(Value value) + public Map convert(final Value value) { - Map result = new HashMap<>(); + final Map result = new HashMap<>(); if (value instanceof MapValue) { - for (Entry entry : ((MapValue) value).getMap().entrySet()) + for (final Entry entry : ((MapValue) value).getMap().entrySet()) { - K key = keyConverter.convert(entry.getKey()); - V val = valueConverter.convert(entry.getValue()); + final K key = keyConverter.convert(entry.getKey()); + final V val = valueConverter.convert(entry.getValue()); if (key == null || val == null) + { return null; + } result.put(key, val); } return result; @@ -55,8 +57,9 @@ class MapConverter implements ValueConverter> return null; } - private MapConverter(AnnotatedType keyType, AnnotatedType valueType) + private MapConverter(final AnnotatedType keyType, final AnnotatedType valueType) { + super(); keyConverter = ValueConverter.fromAnnotatedType(keyType); valueConverter = ValueConverter.fromAnnotatedType(valueType); } @@ -77,9 +80,9 @@ class MapConverter implements ValueConverter> * @param annotatedType The type to get generics information from * @return A new {@link MapConverter} for the data specified in the {@link AnnotatedType} */ - static MapConverter fromAnnotatedType(AnnotatedType annotatedType) + static MapConverter fromAnnotatedType(final AnnotatedType annotatedType) { - AnnotatedType[] annotatedGenerics = ((AnnotatedParameterizedType) annotatedType).getAnnotatedActualTypeArguments(); + final AnnotatedType[] annotatedGenerics = ((AnnotatedParameterizedType) annotatedType).getAnnotatedActualTypeArguments(); return annotatedType.isAnnotationPresent(Param.KeyValuePairs.class) ? new PairConverter<>(annotatedGenerics[0], annotatedGenerics[1], annotatedType.getAnnotation(Param.KeyValuePairs.class)) : new MapConverter<>(annotatedGenerics[0], annotatedGenerics[1]); @@ -89,7 +92,7 @@ class MapConverter implements ValueConverter> { private final boolean acceptMultiParam; - private PairConverter(AnnotatedType keyType, AnnotatedType valueType, Param.KeyValuePairs config) + private PairConverter(final AnnotatedType keyType, final AnnotatedType valueType, final Param.KeyValuePairs config) { super(keyType, valueType); acceptMultiParam = config.allowMultiparam(); @@ -102,51 +105,63 @@ class MapConverter implements ValueConverter> } @Override - public Map convert(Value value) { + public Map convert(final Value value) { return value instanceof MapValue ? super.convert(value) : value instanceof ListValue ? convertList(((ListValue)value).getItems()) : null; // Multiparam mode can only be used in evalAndConvert } - private Map convertList(List valueList) + private Map convertList(final List valueList) { if (valueList.size() % 2 == 1) + { return null; - Map map = new HashMap<>(); - Iterator val = valueList.iterator(); + } + final Map map = new HashMap<>(); + final Iterator val = valueList.iterator(); while (val.hasNext()) { - K key = keyConverter.convert(val.next()); - V value = valueConverter.convert(val.next()); + final K key = keyConverter.convert(val.next()); + final V value = valueConverter.convert(val.next()); if (key == null || value == null) + { return null; + } map.put(key, value); } return map; } @Override - public Map checkAndConvert(Iterator valueIterator, Context context, Context.Type theLazyT) + public Map checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type theLazyT) { if (!valueIterator.hasNext()) + { return null; - Value val = valueIterator.next(); + } + final Value val = valueIterator.next(); if (!acceptMultiParam || val instanceof MapValue || (val instanceof ListValue && !(keyConverter instanceof ListConverter))) + { return convert(val); // @KeyValuePairs Map, Boolean> will not support list consumption + } - Map map = new HashMap<>(); + final Map map = new HashMap<>(); K key = keyConverter.convert(val); //First pair is manual since we got it to check for a different conversion mode V value = valueConverter.checkAndConvert(valueIterator, context, theLazyT); if (key == null || value == null) + { return null; + } map.put(key, value); while (valueIterator.hasNext()) { key = keyConverter.checkAndConvert(valueIterator, context, theLazyT); value = valueConverter.checkAndConvert(valueIterator, context, theLazyT); if (key == null || value == null) + { return null; + } map.put(key, value); } return map; diff --git a/src/main/java/carpet/script/annotation/OptionalConverter.java b/src/main/java/carpet/script/annotation/OptionalConverter.java index e610e9c3..08519157 100644 --- a/src/main/java/carpet/script/annotation/OptionalConverter.java +++ b/src/main/java/carpet/script/annotation/OptionalConverter.java @@ -50,25 +50,33 @@ final class OptionalConverter implements ValueConverter> * {@link #checkAndConvert(Iterator, Context, Context.Type)} and is only used as a fallback in types that don't support it. */ @Override - public Optional convert(Value value) + public Optional convert(final Value value) { if (value.isNull()) + { return Optional.empty(); - R converted = typeConverter.convert(value); + } + final R converted = typeConverter.convert(value); if (converted == null) + { return null; + } return Optional.of(converted); } @Override - public Optional checkAndConvert(Iterator valueIterator, Context context, Context.Type theLazyT) + public Optional checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type theLazyT) { if (!valueIterator.hasNext() || valueIterator.next().isNull()) + { return Optional.empty(); + } ((ListIterator) valueIterator).previous(); - R converted = typeConverter.checkAndConvert(valueIterator, context, theLazyT); + final R converted = typeConverter.checkAndConvert(valueIterator, context, theLazyT); if (converted == null) + { return null; + } return Optional.of(converted); } @@ -98,10 +106,10 @@ final class OptionalConverter implements ValueConverter> * @param annotatedType The type to get generics information from * @return A new {@link OptionalConverter} for the data specified in the {@link AnnotatedType} */ - static OptionalConverter fromAnnotatedType(AnnotatedType annotatedType) + static OptionalConverter fromAnnotatedType(final AnnotatedType annotatedType) { - AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType; - AnnotatedType wrappedType = paramType.getAnnotatedActualTypeArguments()[0]; + final AnnotatedParameterizedType paramType = (AnnotatedParameterizedType) annotatedType; + final AnnotatedType wrappedType = paramType.getAnnotatedActualTypeArguments()[0]; return new OptionalConverter<>(wrappedType); } } diff --git a/src/main/java/carpet/script/annotation/OutputConverter.java b/src/main/java/carpet/script/annotation/OutputConverter.java index 59f99233..b7947618 100644 --- a/src/main/java/carpet/script/annotation/OutputConverter.java +++ b/src/main/java/carpet/script/annotation/OutputConverter.java @@ -58,7 +58,7 @@ public final class OutputConverter private final Function converter; - private OutputConverter(Function converter) + private OutputConverter(final Function converter) { this.converter = converter; } @@ -75,7 +75,9 @@ public final class OutputConverter public static OutputConverter get(Class returnType) { if (Value.class.isAssignableFrom(returnType)) + { return (OutputConverter) VALUE; + } returnType = (Class) ClassUtils.primitiveToWrapper(returnType); // wrapper holds same generic as primitive: wrapped return (OutputConverter) Objects.requireNonNull(byResult.get(returnType), "Unregistered output type: " + returnType + ". Register in OutputConverter"); @@ -89,7 +91,7 @@ public final class OutputConverter * @param input The value to convert * @return The converted value */ - public LazyValue convert(T input) + public LazyValue convert(final T input) { return input == null ? LazyValue.NULL : converter.apply(input); } @@ -102,11 +104,13 @@ public final class OutputConverter * @param inputType The class of T * @param converter The function that converts the an instance of T to a {@link LazyValue} */ - public static void register(Class inputType, Function converter) + public static void register(final Class inputType, final Function converter) { - OutputConverter instance = new OutputConverter(converter); + final OutputConverter instance = new OutputConverter<>(converter); if (byResult.containsKey(inputType)) + { throw new IllegalArgumentException(inputType + " already has a registered OutputConverter"); + } byResult.put(inputType, instance); } @@ -119,11 +123,13 @@ public final class OutputConverter * @param inputType The class of T * @param converter The function that converts an instance of T to a {@link Value} */ - public static void registerToValue(Class inputType, Function converter) + public static void registerToValue(final Class inputType, final Function converter) { - OutputConverter instance = new OutputConverter<>(converter.andThen(v -> (c, t) -> v)); + final OutputConverter instance = new OutputConverter<>(converter.andThen(v -> (c, t) -> v)); if (byResult.containsKey(inputType)) + { throw new IllegalArgumentException(inputType + " already has a registered OutputConverter"); + } byResult.put(inputType, instance); } } diff --git a/src/main/java/carpet/script/annotation/Param.java b/src/main/java/carpet/script/annotation/Param.java index 89ac37fd..7ec081cd 100644 --- a/src/main/java/carpet/script/annotation/Param.java +++ b/src/main/java/carpet/script/annotation/Param.java @@ -51,7 +51,7 @@ public interface Param @Documented @Retention(RUNTIME) @Target({ PARAMETER, TYPE_USE }) - public @interface AllowSingleton + @interface AllowSingleton { } @@ -71,7 +71,7 @@ public interface Param @Documented @Retention(RUNTIME) @Target({ PARAMETER, TYPE_USE }) - public @interface KeyValuePairs + @interface KeyValuePairs { /** *

Whether or not this accepts the key-value pairs directly in the function call as myFunction(..., key, value, key2, value2)

@@ -91,7 +91,7 @@ public interface Param @Documented @Retention(RUNTIME) @Target({ PARAMETER, TYPE_USE }) - public @interface Custom + @interface Custom { } @@ -111,7 +111,7 @@ public interface Param @Documented @Retention(RUNTIME) @Target({ PARAMETER, TYPE_USE }) - public @interface Strict + @interface Strict { /** *

Defines whether this parameter can accept types with "shallow strictness", that is, in order to get a {@link Component}, accepting either a @@ -137,7 +137,7 @@ public interface Param * @see #registerCustomConverterFactory(BiFunction) * */ - public static final class Params + final class Params { /** *

A {@link ValueConverter} that outputs the {@link Context} in which the function has been called, and throws {@link UnsupportedOperationException} when trying to convert a {@link Value} @@ -148,13 +148,13 @@ public interface Param @Override public String getTypeName() { return null; } @Override - public Context convert(Value value) + public Context convert(final Value value) { throw new UnsupportedOperationException("Called convert() with Value in Context Provider converter, where only checkAndConvert is supported"); } @Override - public Context checkAndConvert(Iterator valueIterator, Context context, Context.Type theLazyT) + public Context checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type theLazyT) { return context; } @@ -175,13 +175,13 @@ public interface Param @Override public String getTypeName() { return null; } @Override - public Context.Type convert(Value value) + public Context.Type convert(final Value value) { throw new UnsupportedOperationException("Called convert() with a Value in TheLazyT Provider, where only checkAndConvert is supported"); } @Override - public Context.Type checkAndConvert(Iterator valueIterator, Context context, Context.Type theLazyT) + public Context.Type checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type theLazyT) { return theLazyT; } @@ -193,7 +193,7 @@ public interface Param } }; - static record StrictConverterInfo(Class type, boolean shallow) {} + record StrictConverterInfo(Class type, boolean shallow) {} private static final Map> strictParamsByClassAndShallowness = new HashMap<>(); static { // TODO Specify strictness in name? @@ -214,14 +214,16 @@ public interface Param * @throws IllegalArgumentException If the type doesn't accept the {@link Strict} annotation or if it has been used incorrectly (shallow in * unsupported places) */ - static ValueConverter getStrictConverter(AnnotatedType type) + static ValueConverter getStrictConverter(final AnnotatedType type) { - boolean shallow = type.getAnnotation(Strict.class).shallow(); - Class clazz = (Class) type.getType(); - var key = new StrictConverterInfo(clazz, shallow); - ValueConverter converter = strictParamsByClassAndShallowness.get(key); + final boolean shallow = type.getAnnotation(Strict.class).shallow(); + final Class clazz = (Class) type.getType(); + final StrictConverterInfo key = new StrictConverterInfo(clazz, shallow); + final ValueConverter converter = strictParamsByClassAndShallowness.get(key); if (converter != null) + { return converter; + } throw new IllegalArgumentException("Incorrect use of @Param.Strict annotation"); } @@ -237,11 +239,13 @@ public interface Param * @param shallow {@code true} if you are registering a shallow-strict parameter, {@code false} if a "fully" strict one * @param converter The {@link ValueConverter} for the given type and shallowness. */ - public static void registerStrictConverter(Class type, boolean shallow, ValueConverter converter) + public static void registerStrictConverter(final Class type, final boolean shallow, final ValueConverter converter) { - var key = new StrictConverterInfo(type, shallow); + final StrictConverterInfo key = new StrictConverterInfo(type, shallow); if (strictParamsByClassAndShallowness.containsKey(key)) + { throw new IllegalArgumentException(type + " already has a registered " + (shallow ? "" : "non-") + "shallow StrictConverter"); + } strictParamsByClassAndShallowness.put(key, converter); } @@ -267,19 +271,21 @@ public interface Param * avoid possible collisions with other extensions. */ @SuppressWarnings("unchecked") // this makes no sense... But I guess its preferable to enforce typesafety in callers - public static void registerCustomConverterFactory(BiFunction, ValueConverter> factory) + public static void registerCustomConverterFactory(final BiFunction, ValueConverter> factory) { customFactories.add((BiFunction, ValueConverter>) (Object) factory); } @SuppressWarnings("unchecked") // Stored correctly - static ValueConverter getCustomConverter(AnnotatedType annoType, Class type) + static ValueConverter getCustomConverter(final AnnotatedType annoType, final Class type) { ValueConverter result; - for (BiFunction, ValueConverter> factory : customFactories) + for (final BiFunction, ValueConverter> factory : customFactories) { if ((result = (ValueConverter) factory.apply(annoType, type)) != null) + { return result; + } } throw new IllegalArgumentException("No custom converter found for Param.Custom annotated param with type " + annoType.getType().getTypeName()); } diff --git a/src/main/java/carpet/script/annotation/ScarpetFunction.java b/src/main/java/carpet/script/annotation/ScarpetFunction.java index 745760b7..c4ad698f 100644 --- a/src/main/java/carpet/script/annotation/ScarpetFunction.java +++ b/src/main/java/carpet/script/annotation/ScarpetFunction.java @@ -53,7 +53,7 @@ public @interface ScarpetFunction /** *

Used to define that this {@link ScarpetFunction} can accept an unlimited number of parameters

*/ - public static final int UNLIMITED_PARAMS = -1; + int UNLIMITED_PARAMS = -1; /** *

If the function can accept a variable number of parameters, either by declaring its last parameter as a varargs parameter or by having one diff --git a/src/main/java/carpet/script/annotation/SimpleTypeConverter.java b/src/main/java/carpet/script/annotation/SimpleTypeConverter.java index 498e3b36..e6beccba 100644 --- a/src/main/java/carpet/script/annotation/SimpleTypeConverter.java +++ b/src/main/java/carpet/script/annotation/SimpleTypeConverter.java @@ -58,8 +58,9 @@ public final class SimpleTypeConverter implements ValueConve * @param inputType The required type for the input {@link Value} * @param converter The function to convert an instance of inputType into R. */ - public SimpleTypeConverter(Class inputType, Function converter, String typeName) + public SimpleTypeConverter(final Class inputType, final Function converter, final String typeName) { + super(); this.converter = converter; this.valueClass = inputType; this.typeName = typeName; @@ -79,14 +80,14 @@ public final class SimpleTypeConverter implements ValueConve * @return The {@link SimpleTypeConverter} for the specified outputType */ @SuppressWarnings("unchecked") // T always extends Value, R is always the same as map's key, since map is private. - static SimpleTypeConverter get(Class outputType) + static SimpleTypeConverter get(final Class outputType) { return (SimpleTypeConverter) byResult.get(outputType); } @Override @SuppressWarnings("unchecked") // more than checked. not using class.cast because then "method is too big" for inlining, because javac is useless - public R convert(Value value) // and adds millions of casts. This one is even removed + public R convert(final Value value) // and adds millions of casts. This one is even removed { return valueClass.isInstance(value) ? converter.apply((T)value) : null; } @@ -103,10 +104,10 @@ public final class SimpleTypeConverter implements ValueConve * can also throw an {@link InternalExpressionException} by itself if really necessary. * @param typeName The name of the type, following the conventions of {@link ValueConverter#getTypeName()} */ - public static void registerType(Class requiredInputType, Class outputType, - Function converter, String typeName) + public static void registerType(final Class requiredInputType, final Class outputType, + final Function converter, final String typeName) { - SimpleTypeConverter type = new SimpleTypeConverter<>(requiredInputType, converter, typeName); + final SimpleTypeConverter type = new SimpleTypeConverter<>(requiredInputType, converter, typeName); byResult.put(outputType, type); } } diff --git a/src/main/java/carpet/script/annotation/ValueCaster.java b/src/main/java/carpet/script/annotation/ValueCaster.java index 1ca8fee7..cc8c01ce 100644 --- a/src/main/java/carpet/script/annotation/ValueCaster.java +++ b/src/main/java/carpet/script/annotation/ValueCaster.java @@ -50,8 +50,9 @@ public final class ValueCaster implements ValueConverter // R always exten private final Class outputType; private final String typeName; - private ValueCaster(Class outputType, String typeName) + private ValueCaster(final Class outputType, final String typeName) { + super(); this.outputType = outputType; this.typeName = typeName; } @@ -71,17 +72,19 @@ public final class ValueCaster implements ValueConverter // R always exten */ @SuppressWarnings("unchecked") // Casters are stored with their exact class, for sure since the map is private (&& class has same generic as // caster) - public static ValueCaster get(Class outputType) + public static ValueCaster get(final Class outputType) { return (ValueCaster) byResult.get(outputType); } @Override @SuppressWarnings("unchecked") // more than checked, see SimpleTypeConverter#converter for reasoning - public R convert(Value value) + public R convert(final Value value) { if (!outputType.isInstance(value)) + { return null; + } return (R)value; } @@ -94,9 +97,9 @@ public final class ValueCaster implements ValueConverter // R always exten * required */ - public static void register(Class valueClass, String typeName) + public static void register(final Class valueClass, final String typeName) { - ValueCaster caster = new ValueCaster(valueClass, typeName); + final ValueCaster caster = new ValueCaster<>(valueClass, typeName); byResult.putIfAbsent(valueClass, caster); } } diff --git a/src/main/java/carpet/script/annotation/ValueConverter.java b/src/main/java/carpet/script/annotation/ValueConverter.java index ed1a1812..ebf39148 100644 --- a/src/main/java/carpet/script/annotation/ValueConverter.java +++ b/src/main/java/carpet/script/annotation/ValueConverter.java @@ -37,7 +37,7 @@ public interface ValueConverter * @apiNote This method is intended to only be called when an error has occurred and therefore there is a need to print a stacktrace with some * helpful usage instructions. */ - public String getTypeName(); + String getTypeName(); /** *

Converts the given {@link Value} to {@code }, which was defined when being registered.

@@ -62,8 +62,7 @@ public interface ValueConverter *

Even with the above reasons, {@link ValueConverter} users should try to implement {@link #convert(Value)} whenever possible instead of * {@link #checkAndConvert(Iterator, Context, Context.Type)}, since it allows its usage in generics of lists and maps.

*/ - @Nullable - public R convert(Value value); + @Nullable R convert(Value value); /** *

Returns whether this {@link ValueConverter} consumes a variable number of elements from the {@link Iterator} passed to it via @@ -72,7 +71,7 @@ public interface ValueConverter * @implNote The default implementation returns {@code false} * @see #valueConsumption() */ - default public boolean consumesVariableArgs() + default boolean consumesVariableArgs() { return false; } @@ -87,7 +86,7 @@ public interface ValueConverter * @implNote The default implementation returns {@code 1} * */ - default public int valueConsumption() + default int valueConsumption() { return 1; } @@ -107,7 +106,7 @@ public interface ValueConverter * @return A usable {@link ValueConverter} to convert from a {@link Value} to {@code } */ @SuppressWarnings("unchecked") - public static ValueConverter fromAnnotatedType(AnnotatedType annoType) + static ValueConverter fromAnnotatedType(final AnnotatedType annoType) { Class type = annoType.getType() instanceof ParameterizedType ? // We are defining R here. (Class) ((ParameterizedType) annoType.getType()).getRawType() : @@ -118,33 +117,51 @@ public interface ValueConverter // Example: AnnotatedGenericTypeArray (or similar) being (@Paran.KeyValuePairs Map... name) // Those will just fail with a ClassCastException. if (type.isArray()) + { type = (Class) type.getComponentType(); // Varargs + } type = (Class) ClassUtils.primitiveToWrapper(type); // It will be boxed anyway, this saves unboxing-boxing if (type == List.class) + { return (ValueConverter) ListConverter.fromAnnotatedType(annoType); // Already checked that type is List + } if (type == Map.class) + { return (ValueConverter) MapConverter.fromAnnotatedType(annoType); // Already checked that type is Map + } if (type == Optional.class) + { return (ValueConverter) OptionalConverter.fromAnnotatedType(annoType); + } if (annoType.getDeclaredAnnotations().length != 0) { if (annoType.isAnnotationPresent(Param.Custom.class)) - return Param.Params.getCustomConverter(annoType, type); // Throws if incorrect usage + { + return Params.getCustomConverter(annoType, type); // Throws if incorrect usage + } if (annoType.isAnnotationPresent(Param.Strict.class)) + { return (ValueConverter) Params.getStrictConverter(annoType); // Throws if incorrect usage + } if (annoType.getAnnotations()[0].annotationType().getEnclosingClass() == Locator.class) + { return Locator.Locators.fromAnnotatedType(annoType, type); + } } // Class only checks if (Value.class.isAssignableFrom(type)) + { return Objects.requireNonNull(ValueCaster.get(type), "Value subclass " + type + " is not registered. Register it in ValueCaster to use it"); - // if (type == LazyValue.class) // No longer supported - // return (ValueConverter) Params.LAZY_VALUE_IDENTITY; + } if (type == Context.class) + { return (ValueConverter) Params.CONTEXT_PROVIDER; + } if (type == Context.Type.class) + { return (ValueConverter) Params.CONTEXT_TYPE_PROVIDER; + } return Objects.requireNonNull(SimpleTypeConverter.get(type), "Type " + type + " is not registered. Register it in SimpleTypeConverter to use it"); } @@ -168,10 +185,8 @@ public interface ValueConverter * @implNote This method's default implementation runs the {@link #convert(Value)} function in the next {@link Value} ignoring {@link Context} and * {@code theLazyT}. */ - default public R checkAndConvert(Iterator valueIterator, Context context, Context.Type contextType) + default R checkAndConvert(final Iterator valueIterator, final Context context, final Context.Type contextType) { - if (!valueIterator.hasNext()) - return null; - return convert(valueIterator.next()); + return !valueIterator.hasNext() ? null : convert(valueIterator.next()); } } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 3357fb87..4faa92fb 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -112,61 +112,67 @@ import static carpet.script.value.NBTSerializableValue.nameFromRegistryId; import static java.lang.Math.max; import static java.lang.Math.min; -public class Auxiliary { +public class Auxiliary +{ public static final String MARKER_STRING = "__scarpet_marker"; private static final Map mixerMap = Arrays.stream(SoundSource.values()).collect(Collectors.toMap(SoundSource::getName, k -> k)); public static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().registerTypeAdapter(Value.class, new ScarpetJsonDeserializer()).create(); @Deprecated - public static String recognizeResource(Value value, boolean isFloder) + public static String recognizeResource(final Value value, final boolean isFloder) { - String origfile = value.getString(); + final String origfile = value.getString(); String file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9\\-+_/]", ""); file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/")); if (file.isEmpty() && !isFloder) { - throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have some letters and numbers"); + throw new InternalExpressionException("Cannot use " + origfile + " as resource name - must have some letters and numbers"); } return file; } - public static void apply(Expression expression) + public static void apply(final Expression expression) { expression.addContextFunction("sound", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; + final CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) { return ListValue.wrap(cc.registry(Registries.SOUND_EVENT).keySet().stream().map(ValueConversions::of)); } - String rawString = lv.get(0).getString(); - ResourceLocation soundName = InputValidator.identifierOf(rawString); - Vector3Argument locator = Vector3Argument.findIn(lv, 1); + final String rawString = lv.get(0).getString(); + final ResourceLocation soundName = InputValidator.identifierOf(rawString); + final Vector3Argument locator = Vector3Argument.findIn(lv, 1); if (cc.registry(Registries.SOUND_EVENT).get(soundName) == null) + { throw new ThrowStatement(rawString, Throwables.UNKNOWN_SOUND); + } final Holder soundHolder = Holder.direct(SoundEvent.createVariableRangeEvent(soundName)); float volume = 1.0F; float pitch = 1.0F; SoundSource mixer = SoundSource.MASTER; - if (lv.size() > 0+locator.offset) + if (lv.size() > 0 + locator.offset) { - volume = (float) NumericValue.asNumber(lv.get(0+locator.offset)).getDouble(); - if (lv.size() > 1+locator.offset) + volume = (float) NumericValue.asNumber(lv.get(0 + locator.offset)).getDouble(); + if (lv.size() > 1 + locator.offset) { - pitch = (float) NumericValue.asNumber(lv.get(1+locator.offset)).getDouble(); - if (lv.size() > 2+locator.offset) + pitch = (float) NumericValue.asNumber(lv.get(1 + locator.offset)).getDouble(); + if (lv.size() > 2 + locator.offset) { - String mixerName = lv.get(2+locator.offset).getString(); + final String mixerName = lv.get(2 + locator.offset).getString(); mixer = mixerMap.get(mixerName.toLowerCase(Locale.ROOT)); - if (mixer == null) throw new InternalExpressionException(mixerName +" is not a valid mixer name"); + if (mixer == null) + { + throw new InternalExpressionException(mixerName + " is not a valid mixer name"); + } } } } - Vec3 vec = locator.vec; - double d0 = Math.pow(volume > 1.0F ? (double)(volume * 16.0F) : 16.0D, 2.0D); + final Vec3 vec = locator.vec; + final double d0 = Math.pow(volume > 1.0F ? (double) (volume * 16.0F) : 16.0D, 2.0D); int count = 0; final ServerLevel level = cc.level(); - long seed = level.getRandom().nextLong(); - for (ServerPlayer player : level.getPlayers( (p) -> p.distanceToSqr(vec) < d0)) + final long seed = level.getRandom().nextLong(); + for (final ServerPlayer player : level.getPlayers((p) -> p.distanceToSqr(vec) < d0)) { count++; player.connection.send(new ClientboundSoundPacket(soundHolder, mixer, vec.x, vec.y, vec.z, volume, pitch, seed)); @@ -176,12 +182,15 @@ public class Auxiliary { expression.addContextFunction("particle", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - if (lv.size() == 0) return ListValue.wrap(cc.registry(Registries.PARTICLE_TYPE).keySet().stream().map(ValueConversions::of)); - MinecraftServer ms = cc.server(); - ServerLevel world = cc.level(); - Vector3Argument locator = Vector3Argument.findIn(lv, 1); - String particleName = lv.get(0).getString(); + final CarpetContext cc = (CarpetContext) c; + if (lv.size() == 0) + { + return ListValue.wrap(cc.registry(Registries.PARTICLE_TYPE).keySet().stream().map(ValueConversions::of)); + } + final MinecraftServer ms = cc.server(); + final ServerLevel world = cc.level(); + final Vector3Argument locator = Vector3Argument.findIn(lv, 1); + final String particleName = lv.get(0).getString(); int count = 10; double speed = 0; float spread = 0.5f; @@ -189,10 +198,10 @@ public class Auxiliary { if (lv.size() > locator.offset) { count = (int) NumericValue.asNumber(lv.get(locator.offset)).getLong(); - if (lv.size() > 1+locator.offset) + if (lv.size() > 1 + locator.offset) { - spread = (float) NumericValue.asNumber(lv.get(1+locator.offset)).getDouble(); - if (lv.size() > 2+locator.offset) + spread = (float) NumericValue.asNumber(lv.get(1 + locator.offset)).getDouble(); + if (lv.size() > 2 + locator.offset) { speed = NumericValue.asNumber(lv.get(2 + locator.offset)).getDouble(); if (lv.size() > 3 + locator.offset) // should accept entity as well as long as it is player @@ -202,13 +211,13 @@ public class Auxiliary { } } } - ParticleOptions particle = ShapeDispatcher.getParticleData(particleName, world.registryAccess()); - Vec3 vec = locator.vec; + final ParticleOptions particle = ShapeDispatcher.getParticleData(particleName, world.registryAccess()); + final Vec3 vec = locator.vec; if (player == null) { - for (Player p : (world.players())) + for (final ServerPlayer p : (world.players())) { - world.sendParticles((ServerPlayer)p, particle, true, vec.x, vec.y, vec.z, count, + world.sendParticles(p, particle, true, vec.x, vec.y, vec.z, count, spread, spread, spread, speed); } } @@ -224,29 +233,32 @@ public class Auxiliary { expression.addContextFunction("particle_line", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerLevel world = cc.level(); - String particleName = lv.get(0).getString(); - ParticleOptions particle = ShapeDispatcher.getParticleData(particleName, world.registryAccess()); - Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); - Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); + final CarpetContext cc = (CarpetContext) c; + final ServerLevel world = cc.level(); + final String particleName = lv.get(0).getString(); + final ParticleOptions particle = ShapeDispatcher.getParticleData(particleName, world.registryAccess()); + final Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); + final Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); double density = 1.0; ServerPlayer player = null; - if (lv.size() > pos2.offset+0 ) + if (lv.size() > pos2.offset + 0) { - density = NumericValue.asNumber(lv.get(pos2.offset+0)).getDouble(); + density = NumericValue.asNumber(lv.get(pos2.offset + 0)).getDouble(); if (density <= 0) { throw new InternalExpressionException("Particle density should be positive"); } - if (lv.size() > pos2.offset+1) + if (lv.size() > pos2.offset + 1) { - Value playerValue = lv.get(pos2.offset+1); - if (playerValue instanceof EntityValue) + final Value playerValue = lv.get(pos2.offset + 1); + if (playerValue instanceof EntityValue entityValue) { - Entity e = ((EntityValue) playerValue).getEntity(); - if (!(e instanceof ServerPlayer)) throw new InternalExpressionException("'particle_line' player argument has to be a player"); - player = (ServerPlayer) e; + final Entity e = entityValue.getEntity(); + if (!(e instanceof final ServerPlayer sp)) + { + throw new InternalExpressionException("'particle_line' player argument has to be a player"); + } + player = sp; } else { @@ -256,39 +268,42 @@ public class Auxiliary { } return new NumericValue(ShapeDispatcher.drawParticleLine( - (player == null)?world.players(): Collections.singletonList(player), + (player == null) ? world.players() : Collections.singletonList(player), particle, pos1.vec, pos2.vec, density )); }); - expression.addContextFunction("item_display_name", 1, (c, t, lv) -> new FormattedTextValue(ValueConversions.getItemStackFromValue(lv.get(0), false, ((CarpetContext)c).registryAccess()).getHoverName())); + expression.addContextFunction("item_display_name", 1, (c, t, lv) -> new FormattedTextValue(ValueConversions.getItemStackFromValue(lv.get(0), false, ((CarpetContext) c).registryAccess()).getHoverName())); expression.addContextFunction("particle_box", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerLevel world = cc.level(); - String particleName = lv.get(0).getString(); - ParticleOptions particle = ShapeDispatcher.getParticleData(particleName, world.registryAccess() ); - Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); - Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); + final CarpetContext cc = (CarpetContext) c; + final ServerLevel world = cc.level(); + final String particleName = lv.get(0).getString(); + final ParticleOptions particle = ShapeDispatcher.getParticleData(particleName, world.registryAccess()); + final Vector3Argument pos1 = Vector3Argument.findIn(lv, 1); + final Vector3Argument pos2 = Vector3Argument.findIn(lv, pos1.offset); double density = 1.0; ServerPlayer player = null; - if (lv.size() > pos2.offset+0 ) + if (lv.size() > pos2.offset + 0) { - density = NumericValue.asNumber(lv.get(pos2.offset+0)).getDouble(); + density = NumericValue.asNumber(lv.get(pos2.offset + 0)).getDouble(); if (density <= 0) { throw new InternalExpressionException("Particle density should be positive"); } - if (lv.size() > pos2.offset+1) + if (lv.size() > pos2.offset + 1) { - Value playerValue = lv.get(pos2.offset+1); - if (playerValue instanceof EntityValue) + final Value playerValue = lv.get(pos2.offset + 1); + if (playerValue instanceof EntityValue entityValue) { - Entity e = ((EntityValue) playerValue).getEntity(); - if (!(e instanceof ServerPlayer)) throw new InternalExpressionException("'particle_box' player argument has to be a player"); - player = (ServerPlayer) e; + final Entity e = entityValue.getEntity(); + if (!(e instanceof final ServerPlayer sp)) + { + throw new InternalExpressionException("'particle_box' player argument has to be a player"); + } + player = sp; } else { @@ -296,12 +311,12 @@ public class Auxiliary { } } } - Vec3 a = pos1.vec; - Vec3 b = pos2.vec; - Vec3 from = new Vec3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); - Vec3 to = new Vec3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); - int particleCount = ShapeDispatcher.Box.particleMesh( - player==null?world.players():Collections.singletonList(player), + final Vec3 a = pos1.vec; + final Vec3 b = pos2.vec; + final Vec3 from = new Vec3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); + final Vec3 to = new Vec3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); + final int particleCount = ShapeDispatcher.Box.particleMesh( + player == null ? world.players() : Collections.singletonList(player), particle, density, from, to ); return new NumericValue(particleCount); @@ -312,19 +327,25 @@ public class Auxiliary { expression.addContextFunction("draw_shape", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerLevel world = cc.level(); - MinecraftServer server = world.getServer(); - Set playerTargets = new HashSet<>(); - List shapes = new ArrayList<>(); + final CarpetContext cc = (CarpetContext) c; + final ServerLevel world = cc.level(); + final MinecraftServer server = world.getServer(); + final Set playerTargets = new HashSet<>(); + final List shapes = new ArrayList<>(); if (lv.size() == 1) // bulk { - Value specLoad = lv.get(0); - if (!(specLoad instanceof ListValue)) throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); - for (Value list : ((ListValue) specLoad).getItems()) + final Value specLoad = lv.get(0); + if (!(specLoad instanceof final ListValue spec)) { - if (!(list instanceof ListValue)) throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); - shapes.add( ShapeDispatcher.fromFunctionArgs(server, world, ((ListValue) list).getItems(), playerTargets)); + throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); + } + for (final Value list : spec.getItems()) + { + if (!(list instanceof final ListValue inner)) + { + throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); + } + shapes.add(ShapeDispatcher.fromFunctionArgs(server, world, inner.getItems(), playerTargets)); } } else @@ -333,27 +354,30 @@ public class Auxiliary { } ShapeDispatcher.sendShape( - (playerTargets.isEmpty())?cc.level().players():playerTargets, + (playerTargets.isEmpty()) ? cc.level().players() : playerTargets, shapes ); return Value.TRUE; }); - expression.addContextFunction("create_marker", -1, (c, t, lv) ->{ - CarpetContext cc = (CarpetContext)c; + expression.addContextFunction("create_marker", -1, (c, t, lv) -> { + final CarpetContext cc = (CarpetContext) c; BlockState targetBlock = null; - Vector3Argument pointLocator; + final Vector3Argument pointLocator; boolean interactable = true; - Component name; + final Component name; try { - Value nameValue = lv.get(0); + final Value nameValue = lv.get(0); name = nameValue.isNull() ? null : FormattedTextValue.getTextByValue(nameValue); pointLocator = Vector3Argument.findIn(lv, 1, true, false); - if (lv.size()>pointLocator.offset) + if (lv.size() > pointLocator.offset) { - BlockArgument blockLocator = BlockArgument.findIn(cc, lv, pointLocator.offset, true, true, false); - if (blockLocator.block != null) targetBlock = blockLocator.block.getBlockState(); + final BlockArgument blockLocator = BlockArgument.findIn(cc, lv, pointLocator.offset, true, true, false); + if (blockLocator.block != null) + { + targetBlock = blockLocator.block.getBlockState(); + } if (lv.size() > blockLocator.offset) { interactable = lv.get(blockLocator.offset).getBoolean(); @@ -364,9 +388,9 @@ public class Auxiliary { { throw new InternalExpressionException("'create_marker' requires a name and three coordinates, with optional direction, and optional block on its head"); } - Level level = cc.level(); - ArmorStand armorstand = new ArmorStand(EntityType.ARMOR_STAND, level); - double yoffset; + final Level level = cc.level(); + final ArmorStand armorstand = new ArmorStand(EntityType.ARMOR_STAND, level); + final double yoffset; if (targetBlock == null && name == null) { yoffset = 0.0; @@ -377,13 +401,13 @@ public class Auxiliary { } else { - if (targetBlock==null) + if (targetBlock == null) { - yoffset = -armorstand.getBbHeight()-0.41; + yoffset = -armorstand.getBbHeight() - 0.41; } else { - yoffset = -armorstand.getBbHeight()+0.3; + yoffset = -armorstand.getBbHeight() + 0.3; } } armorstand.moveTo( @@ -391,34 +415,36 @@ public class Auxiliary { //pointLocator.vec.y - ((!interactable && targetBlock == null)?0.41f:((targetBlock==null)?(armorstand.getHeight()+0.41):(armorstand.getHeight()-0.3))), pointLocator.vec.y + yoffset, pointLocator.vec.z, - (float)pointLocator.yaw, + (float) pointLocator.yaw, (float) pointLocator.pitch ); - armorstand.addTag(MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName())); + armorstand.addTag(MARKER_STRING + "_" + ((cc.host.getName() == null) ? "" : cc.host.getName())); armorstand.addTag(MARKER_STRING); if (targetBlock != null) + { armorstand.setItemSlot(EquipmentSlot.HEAD, new ItemStack(targetBlock.getBlock().asItem())); + } if (name != null) { armorstand.setCustomName(name); armorstand.setCustomNameVisible(true); } - armorstand.setHeadPose(new Rotations((int)pointLocator.pitch,0,0)); + armorstand.setHeadPose(new Rotations((int) pointLocator.pitch, 0, 0)); armorstand.setNoGravity(true); armorstand.setInvisible(true); armorstand.setInvulnerable(true); - armorstand.getEntityData().set(ArmorStand.DATA_CLIENT_FLAGS, (byte)(interactable?8 : 16|8)); + armorstand.getEntityData().set(ArmorStand.DATA_CLIENT_FLAGS, (byte) (interactable ? 8 : 16 | 8)); level.addFreshEntity(armorstand); return new EntityValue(armorstand); }); expression.addContextFunction("remove_all_markers", 0, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; + final CarpetContext cc = (CarpetContext) c; int total = 0; - String markerName = MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName()); - for (Entity e : cc.level().getEntities(EntityType.ARMOR_STAND, (as) -> as.getTags().contains(markerName))) + final String markerName = MARKER_STRING + "_" + ((cc.host.getName() == null) ? "" : cc.host.getName()); + for (final Entity e : cc.level().getEntities(EntityType.ARMOR_STAND, (as) -> as.getTags().contains(markerName))) { - total ++; + total++; e.discard(); // discard // remove(); } return new NumericValue(total); @@ -429,35 +455,49 @@ public class Auxiliary { expression.addUnaryFunction("escape_nbt", v -> new StringValue(StringTag.quoteAndEscape(v.getString()))); expression.addUnaryFunction("parse_nbt", v -> { - if (v instanceof NBTSerializableValue) return ((NBTSerializableValue) v).toValue(); - NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString(), false); - if (ret == null) return Value.NULL; - return ret.toValue(); + if (v instanceof final NBTSerializableValue nbtsv) + { + return nbtsv.toValue(); + } + final NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString(), false); + return ret == null ? Value.NULL : ret.toValue(); }); expression.addFunction("tag_matches", (lv) -> { - int numParam = lv.size(); - if (numParam != 2 && numParam != 3) throw new InternalExpressionException("'tag_matches' requires 2 or 3 arguments"); - if (lv.get(1).isNull()) return Value.TRUE; - if (lv.get(0).isNull()) return Value.FALSE; - Tag source = ((NBTSerializableValue)(NBTSerializableValue.fromValue(lv.get(0)))).getTag(); - Tag match = ((NBTSerializableValue)(NBTSerializableValue.fromValue(lv.get(1)))).getTag(); + final int numParam = lv.size(); + if (numParam != 2 && numParam != 3) + { + throw new InternalExpressionException("'tag_matches' requires 2 or 3 arguments"); + } + if (lv.get(1).isNull()) + { + return Value.TRUE; + } + if (lv.get(0).isNull()) + { + return Value.FALSE; + } + final Tag source = ((NBTSerializableValue) (NBTSerializableValue.fromValue(lv.get(0)))).getTag(); + final Tag match = ((NBTSerializableValue) (NBTSerializableValue.fromValue(lv.get(1)))).getTag(); return BooleanValue.of(NbtUtils.compareNbt(match, source, numParam == 2 || lv.get(2).getBoolean())); }); expression.addFunction("encode_nbt", lv -> { - int argSize = lv.size(); - if (argSize==0 || argSize > 2) throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters"); - Value v = lv.get(0); - boolean force = (argSize > 1) && lv.get(1).getBoolean(); - Tag tag; + final int argSize = lv.size(); + if (argSize == 0 || argSize > 2) + { + throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters"); + } + final Value v = lv.get(0); + final boolean force = (argSize > 1) && lv.get(1).getBoolean(); + final Tag tag; try { tag = v.toTag(force); } - catch (NBTSerializableValue.IncompatibleTypeException ignored) + catch (final NBTSerializableValue.IncompatibleTypeException exception) { - throw new InternalExpressionException("cannot reliably encode to a tag the value of '"+ignored.val.getPrettyString()+"'"); + throw new InternalExpressionException("cannot reliably encode to a tag the value of '" + exception.val.getPrettyString() + "'"); } return new NBTSerializableValue(tag); }); @@ -465,24 +505,30 @@ public class Auxiliary { //"overridden" native call that prints to stderr expression.addContextFunction("print", -1, (c, t, lv) -> { - if (lv.size() == 0 || lv.size() > 2) throw new InternalExpressionException("'print' takes one or two arguments"); - CommandSourceStack s = ((CarpetContext)c).source(); - MinecraftServer server = s.getServer(); + if (lv.size() == 0 || lv.size() > 2) + { + throw new InternalExpressionException("'print' takes one or two arguments"); + } + final CommandSourceStack s = ((CarpetContext) c).source(); + final MinecraftServer server = s.getServer(); Value res = lv.get(0); List targets = null; if (lv.size() == 2) { - List playerValues = (res instanceof ListValue)?((ListValue) res).getItems():Collections.singletonList(res); - List playerTargets = new ArrayList<>(); + final List playerValues = (res instanceof ListValue list) ? list.getItems() : Collections.singletonList(res); + final List playerTargets = new ArrayList<>(); playerValues.forEach(pv -> { - ServerPlayer player = EntityValue.getPlayerByValue(server, pv); - if (player == null) throw new InternalExpressionException("Cannot target player "+pv.getString()+" in print"); + final ServerPlayer player = EntityValue.getPlayerByValue(server, pv); + if (player == null) + { + throw new InternalExpressionException("Cannot target player " + pv.getString() + " in print"); + } playerTargets.add(player); }); targets = playerTargets; res = lv.get(1); } - Component message = FormattedTextValue.getTextByValue(res); + final Component message = FormattedTextValue.getTextByValue(res); if (targets == null) { s.sendSuccess(message, false); @@ -495,55 +541,62 @@ public class Auxiliary { }); expression.addContextFunction("display_title", -1, (c, t, lv) -> { - if (lv.size() < 2) throw new InternalExpressionException("'display_title' needs at least a target, type and message, and optionally times"); - Value pVal = lv.get(0); - if (!(pVal instanceof ListValue)) pVal = ListValue.of(pVal); - MinecraftServer server = ((CarpetContext)c).server(); - Stream targets = ((ListValue) pVal).getItems().stream().map(v -> + if (lv.size() < 2) { - ServerPlayer player = EntityValue.getPlayerByValue(server, v); - if (player == null) throw new InternalExpressionException("'display_title' requires a valid online player or a list of players as first argument. "+v.getString()+" is not a player."); + throw new InternalExpressionException("'display_title' needs at least a target, type and message, and optionally times"); + } + Value pVal = lv.get(0); + if (!(pVal instanceof ListValue)) + { + pVal = ListValue.of(pVal); + } + final MinecraftServer server = ((CarpetContext) c).server(); + final Stream targets = ((ListValue) pVal).getItems().stream().map(v -> + { + final ServerPlayer player = EntityValue.getPlayerByValue(server, v); + if (player == null) + { + throw new InternalExpressionException("'display_title' requires a valid online player or a list of players as first argument. " + v.getString() + " is not a player."); + } return player; }); Function> packetGetter = null; - //TitleS2CPacket.Action action; - String actionString = lv.get(1).getString().toLowerCase(Locale.ROOT); + final String actionString = lv.get(1).getString().toLowerCase(Locale.ROOT); switch (actionString) { case "title": packetGetter = ClientboundSetTitleTextPacket::new; - //action = Action.TITLE; if (lv.size() < 3) + { throw new InternalExpressionException("Third argument of 'display_title' must be present except for 'clear' type"); + } break; case "subtitle": packetGetter = ClientboundSetSubtitleTextPacket::new; if (lv.size() < 3) + { throw new InternalExpressionException("Third argument of 'display_title' must be present except for 'clear' type"); + } - //action = Action.SUBTITLE; break; case "actionbar": packetGetter = ClientboundSetActionBarTextPacket::new; if (lv.size() < 3) + { throw new InternalExpressionException("Third argument of 'display_title' must be present except for 'clear' type"); + } - //action = Action.ACTIONBAR; break; case "clear": - packetGetter = (x) -> new ClientboundClearTitlesPacket(true); // resetting default fade - //action = Action.CLEAR; + packetGetter = x -> new ClientboundClearTitlesPacket(true); // resetting default fade break; - case "player_list_header": - case "player_list_footer": + case "player_list_header", "player_list_footer": break; default: throw new InternalExpressionException("'display_title' requires 'title', 'subtitle', 'actionbar', 'player_list_header', 'player_list_footer' or 'clear' as second argument"); } - //if (action != Action.CLEAR && lv.size() < 3) - // throw new InternalExpressionException("Third argument of 'display_title' must be present except for 'clear' type"); - Component title; + final Component title; boolean soundsTrue = false; if (lv.size() > 2) { @@ -551,47 +604,65 @@ public class Auxiliary { title = FormattedTextValue.getTextByValue(pVal); soundsTrue = pVal.getBoolean(); } - else title = null; // Will never happen, just to make lambda happy + else + { + title = null; // Will never happen, just to make lambda happy + } if (packetGetter == null) { - Map map; + final Map map; if (actionString.equals("player_list_header")) + { map = HUDController.scarpet_headers; + } else + { map = HUDController.scarpet_footers; + } - AtomicInteger total = new AtomicInteger(0); - List targetList = targets.collect(Collectors.toList()); + final AtomicInteger total = new AtomicInteger(0); + final List targetList = targets.collect(Collectors.toList()); if (!soundsTrue) // null or empty string + { targetList.forEach(target -> { map.remove(target.getScoreboardName()); total.getAndIncrement(); }); + } else + { targetList.forEach(target -> { map.put(target.getScoreboardName(), title); total.getAndIncrement(); }); - HUDController.update_hud(((CarpetContext)c).server(), targetList); + } + HUDController.update_hud(((CarpetContext) c).server(), targetList); return NumericValue.of(total.get()); } - ClientboundSetTitlesAnimationPacket timesPacket; // TimesPacket + final ClientboundSetTitlesAnimationPacket timesPacket; // TimesPacket if (lv.size() > 3) { - if (lv.size() != 6) throw new InternalExpressionException("'display_title' needs all fade-in, stay and fade-out times"); - int in = NumericValue.asNumber(lv.get(3),"fade in for display_title" ).getInt(); - int stay = NumericValue.asNumber(lv.get(4),"stay for display_title" ).getInt(); - int out = NumericValue.asNumber(lv.get(5),"fade out for display_title" ).getInt(); + if (lv.size() != 6) + { + throw new InternalExpressionException("'display_title' needs all fade-in, stay and fade-out times"); + } + final int in = NumericValue.asNumber(lv.get(3), "fade in for display_title").getInt(); + final int stay = NumericValue.asNumber(lv.get(4), "stay for display_title").getInt(); + final int out = NumericValue.asNumber(lv.get(5), "fade out for display_title").getInt(); timesPacket = new ClientboundSetTitlesAnimationPacket(in, stay, out); - //timesPacket = new TitleS2CPacket(Action.TIMES, null, in, stay, out); } - else timesPacket = null; + else + { + timesPacket = null; + } - Packet packet = packetGetter.apply(title); - //TitleS2CPacket packet = new TitleS2CPacket(action, title); - AtomicInteger total = new AtomicInteger(0); + final Packet packet = packetGetter.apply(title); + final AtomicInteger total = new AtomicInteger(0); targets.forEach(p -> { - if (timesPacket != null) p.connection.send(timesPacket); + if (timesPacket != null) + { + p.connection.send(timesPacket); + } p.connection.send(packet); total.getAndIncrement(); }); @@ -599,20 +670,25 @@ public class Auxiliary { }); expression.addFunction("format", values -> { - if (values.size() == 0 ) throw new InternalExpressionException("'format' requires at least one component"); - if (values.get(0) instanceof ListValue && values.size()==1) - values = ((ListValue) values.get(0)).getItems(); + if (values.size() == 0) + { + throw new InternalExpressionException("'format' requires at least one component"); + } + if (values.get(0) instanceof final ListValue list && values.size() == 1) + { + values = list.getItems(); + } return new FormattedTextValue(Messenger.c(values.stream().map(Value::getString).toArray())); }); expression.addContextFunction("run", 1, (c, t, lv) -> { - CommandSourceStack s = ((CarpetContext)c).source(); + final CommandSourceStack s = ((CarpetContext) c).source(); try { - Component[] error = {null}; - List output = new ArrayList<>(); - Value retval = new NumericValue(s.getServer().getCommands().performPrefixedCommand( + final Component[] error = {null}; + final List output = new ArrayList<>(); + final Value retval = new NumericValue(s.getServer().getCommands().performPrefixedCommand( new SnoopyCommandSource(s, error, output), lv.get(0).getString()) ); @@ -622,7 +698,7 @@ public class Auxiliary { FormattedTextValue.of(error[0]) ); } - catch (Exception exc) + catch (final Exception exc) { return ListValue.of(Value.NULL, ListValue.of(), new FormattedTextValue(Component.literal(exc.getMessage()))); } @@ -630,10 +706,10 @@ public class Auxiliary { expression.addContextFunction("save", 0, (c, t, lv) -> { - CommandSourceStack s = ((CarpetContext)c).source(); + final CommandSourceStack s = ((CarpetContext) c).source(); s.getServer().getPlayerList().saveAll(); - s.getServer().saveAllChunks(true,true,true); - for (ServerLevel world : s.getServer().getAllLevels()) + s.getServer().saveAllChunks(true, true, true); + for (final ServerLevel world : s.getServer().getAllLevels()) { world.getChunkSource().tick(() -> true, false); } @@ -651,11 +727,14 @@ public class Auxiliary { expression.addContextFunction("day_time", -1, (c, t, lv) -> { - Value time = new NumericValue(((CarpetContext) c).level().getDayTime()); + final Value time = new NumericValue(((CarpetContext) c).level().getDayTime()); if (lv.size() > 0) { long newTime = NumericValue.asNumber(lv.get(0)).getLong(); - if (newTime < 0) newTime = 0; + if (newTime < 0) + { + newTime = 0; + } ((CarpetContext) c).level().setDayTime(newTime); } return time; @@ -664,33 +743,41 @@ public class Auxiliary { expression.addContextFunction("last_tick_times", -1, (c, t, lv) -> { c.host.issueDeprecation("last_tick_times()"); - return SystemInfo.get("server_last_tick_times", (CarpetContext)c); + return SystemInfo.get("server_last_tick_times", (CarpetContext) c); }); expression.addContextFunction("game_tick", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - //CommandSourceStack s = cc.source(); - MinecraftServer server = cc.server(); - if (CarpetServer.scriptServer == null) return Value.NULL; - if (!server.isSameThread()) throw new InternalExpressionException("Unable to run ticks from threads"); - if (CarpetServer.scriptServer.tickDepth > 16) throw new InternalExpressionException("'game_tick' function caused other 'game_tick' functions to run. You should not allow that."); + final CarpetContext cc = (CarpetContext) c; + final MinecraftServer server = cc.server(); + if (CarpetServer.scriptServer == null) + { + return Value.NULL; + } + if (!server.isSameThread()) + { + throw new InternalExpressionException("Unable to run ticks from threads"); + } + if (CarpetServer.scriptServer.tickDepth > 16) + { + throw new InternalExpressionException("'game_tick' function caused other 'game_tick' functions to run. You should not allow that."); + } try { - CarpetServer.scriptServer.tickDepth ++; + CarpetServer.scriptServer.tickDepth++; ((MinecraftServerInterface) server).forceTick(() -> System.nanoTime() - CarpetServer.scriptServer.tickStart < 50000000L); if (lv.size() > 0) { - long ms_total = NumericValue.asNumber(lv.get(0)).getLong(); - long end_expected = CarpetServer.scriptServer.tickStart + ms_total * 1000000L; - long wait = end_expected - System.nanoTime(); + final long ms_total = NumericValue.asNumber(lv.get(0)).getLong(); + final long end_expected = CarpetServer.scriptServer.tickStart + ms_total * 1000000L; + final long wait = end_expected - System.nanoTime(); if (wait > 0L) { try { Thread.sleep(wait / 1000000L); } - catch (InterruptedException ignored) + catch (final InterruptedException ignored) { } } @@ -701,25 +788,29 @@ public class Auxiliary { finally { if (CarpetServer.scriptServer != null) - CarpetServer.scriptServer.tickDepth --; + { + CarpetServer.scriptServer.tickDepth--; + } } - if(CarpetServer.scriptServer != null && CarpetServer.scriptServer.stopAll) + if (CarpetServer.scriptServer != null && CarpetServer.scriptServer.stopAll) + { throw new ExitStatement(Value.NULL); + } return Value.TRUE; }); expression.addContextFunction("seed", -1, (c, t, lv) -> { - CommandSourceStack s = ((CarpetContext)c).source(); + final CommandSourceStack s = ((CarpetContext) c).source(); c.host.issueDeprecation("seed()"); return new NumericValue(s.getLevel().getSeed()); }); expression.addContextFunction("relight", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - BlockPos pos = locator.block.getPos(); - ServerLevel world = cc.level(); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final BlockPos pos = locator.block.getPos(); + final ServerLevel world = cc.level(); ((ThreadedAnvilChunkStorageInterface) world.getChunkSource().chunkMap).relightChunk(new ChunkPos(pos)); WorldTools.forceChunkUpdate(pos, world); return Value.TRUE; @@ -727,32 +818,35 @@ public class Auxiliary { // Should this be deprecated for system_info('source_dimension')? expression.addContextFunction("current_dimension", 0, (c, t, lv) -> - ValueConversions.of( ((CarpetContext)c).level())); + ValueConversions.of(((CarpetContext) c).level())); expression.addContextFunction("view_distance", 0, (c, t, lv) -> { c.host.issueDeprecation("view_distance()"); - return new NumericValue(((CarpetContext)c).server().getPlayerList().getViewDistance()); + return new NumericValue(((CarpetContext) c).server().getPlayerList().getViewDistance()); }); // lazy due to passthrough and context changing ability expression.addLazyFunction("in_dimension", 2, (c, t, lv) -> { - CommandSourceStack outerSource = ((CarpetContext)c).source(); - Value dimensionValue = lv.get(0).evalValue(c); - Level world = ValueConversions.dimFromValue(dimensionValue, outerSource.getServer()); - if (world == outerSource.getLevel()) return lv.get(1); - CommandSourceStack innerSource = outerSource.withLevel((ServerLevel)world); - Context newCtx = c.recreate(); + final CommandSourceStack outerSource = ((CarpetContext) c).source(); + final Value dimensionValue = lv.get(0).evalValue(c); + final Level world = ValueConversions.dimFromValue(dimensionValue, outerSource.getServer()); + if (world == outerSource.getLevel()) + { + return lv.get(1); + } + final CommandSourceStack innerSource = outerSource.withLevel((ServerLevel) world); + final Context newCtx = c.recreate(); ((CarpetContext) newCtx).swapSource(innerSource); newCtx.variables = c.variables; - Value retval = lv.get(1).evalValue(newCtx); + final Value retval = lv.get(1).evalValue(newCtx); return (cc, tt) -> retval; }); - expression.addContextFunction("plop", -1, (c, t, lv) ->{ + expression.addContextFunction("plop", -1, (c, t, lv) -> { if (lv.size() == 0) { - Map plopData = new HashMap<>(); - CarpetContext cc = (CarpetContext)c; + final Map plopData = new HashMap<>(); + final CarpetContext cc = (CarpetContext) c; plopData.put(StringValue.of("scarpet_custom"), ListValue.wrap(FeatureGenerator.featureMap.keySet().stream().sorted().map(StringValue::of)) ); @@ -770,30 +864,38 @@ public class Auxiliary { ); return MapValue.wrap(plopData); } - BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); + final BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); if (lv.size() <= locator.offset) - throw new InternalExpressionException("'plop' needs extra argument indicating what to plop"); - String what = lv.get(locator.offset).getString(); - Value [] result = new Value[]{Value.NULL}; - ((CarpetContext)c).server().executeBlocking( () -> { - Boolean res = FeatureGenerator.plop(what, ((CarpetContext) c).level(), locator.block.getPos()); + throw new InternalExpressionException("'plop' needs extra argument indicating what to plop"); + } + final String what = lv.get(locator.offset).getString(); + final Value[] result = new Value[]{Value.NULL}; + ((CarpetContext) c).server().executeBlocking(() -> + { + final Boolean res = FeatureGenerator.plop(what, ((CarpetContext) c).level(), locator.block.getPos()); if (res == null) + { return; + } if (what.equalsIgnoreCase("forest_rock")) // there might be more of those + { WorldTools.forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).level()); + } result[0] = BooleanValue.of(res); }); return result[0]; }); expression.addContextFunction("schedule", -1, (c, t, lv) -> { - if (lv.size()<2) + if (lv.size() < 2) + { throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); - long delay = NumericValue.asNumber(lv.get(0)).getLong(); + } + final long delay = NumericValue.asNumber(lv.get(0)).getLong(); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); + final FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, false); CarpetServer.scriptServer.events.scheduleCall( (CarpetContext) c, functionArgument.function, @@ -805,103 +907,99 @@ public class Auxiliary { expression.addImpureFunction("logger", lv -> { - Value res; + final Value res; - if(lv.size()==1) + if (lv.size() == 1) { res = lv.get(0); CarpetScriptServer.LOG.info(res.getString()); } - else if(lv.size()==2) + else if (lv.size() == 2) { - String level = lv.get(0).getString().toLowerCase(Locale.ROOT); + final String level = lv.get(0).getString().toLowerCase(Locale.ROOT); res = lv.get(1); - switch(level){ - case "debug": CarpetScriptServer.LOG.debug(res.getString()); break; - case "warn": CarpetScriptServer.LOG.warn(res.getString()); break; - case "info": CarpetScriptServer.LOG.info(res.getString()); break; - case "fatal": - // Somehow issue deprecation - case "error": - CarpetScriptServer.LOG.error(res.getString()); - break; - default: throw new InternalExpressionException("Unknown log level for 'logger': "+level); + switch (level) + { + case "debug" -> CarpetScriptServer.LOG.debug(res.getString()); + case "warn" -> CarpetScriptServer.LOG.warn(res.getString()); + case "info" -> CarpetScriptServer.LOG.info(res.getString()); + // Somehow issue deprecation + case "fatal", "error" -> CarpetScriptServer.LOG.error(res.getString()); + default -> throw new InternalExpressionException("Unknown log level for 'logger': " + level); } } - else throw new InternalExpressionException("logger takes 1 or 2 arguments"); + else + { + throw new InternalExpressionException("logger takes 1 or 2 arguments"); + } return res; // pass through for variables }); expression.addContextFunction("list_files", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv,true, FileArgument.Reason.READ); - Stream files = ((CarpetScriptHost) c.host).listFolder(fdesc); - if (files == null) return Value.NULL; - return ListValue.wrap(files.map(StringValue::of)); + final FileArgument fdesc = FileArgument.from(lv, true, FileArgument.Reason.READ); + final Stream files = ((CarpetScriptHost) c.host).listFolder(fdesc); + return files == null ? Value.NULL : ListValue.wrap(files.map(StringValue::of)); }); expression.addContextFunction("read_file", 2, (c, t, lv) -> { - FileArgument fdesc = FileArgument.from(lv,false, FileArgument.Reason.READ); - Value retVal; + final FileArgument fdesc = FileArgument.from(lv, false, FileArgument.Reason.READ); if (fdesc.type == FileArgument.Type.NBT) { - Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc); - if (state == null) return Value.NULL; - retVal = new NBTSerializableValue(state); + final Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc); + return state == null ? Value.NULL : new NBTSerializableValue(state); } else if (fdesc.type == FileArgument.Type.JSON) { - JsonElement json; + final JsonElement json; json = ((CarpetScriptHost) c.host).readJsonFile(fdesc); - Value parsedJson = GSON.fromJson(json, Value.class); - if (parsedJson == null) - retVal = Value.NULL; - else - retVal = parsedJson; + final Value parsedJson = GSON.fromJson(json, Value.class); + return parsedJson == null ? Value.NULL : parsedJson; } else { - List content = ((CarpetScriptHost) c.host).readTextResource(fdesc); - if (content == null) return Value.NULL; - retVal = ListValue.wrap(content.stream().map(StringValue::new)); + final List content = ((CarpetScriptHost) c.host).readTextResource(fdesc); + return content == null ? Value.NULL : ListValue.wrap(content.stream().map(StringValue::new)); } - return retVal; }); expression.addContextFunction("delete_file", 2, (c, t, lv) -> - BooleanValue.of(((CarpetScriptHost) c.host).removeResourceFile(FileArgument.from(lv,false, FileArgument.Reason.DELETE)))); + BooleanValue.of(((CarpetScriptHost) c.host).removeResourceFile(FileArgument.from(lv, false, FileArgument.Reason.DELETE)))); expression.addContextFunction("write_file", -1, (c, t, lv) -> { - if (lv.size() < 3) throw new InternalExpressionException("'write_file' requires three or more arguments"); - FileArgument fdesc = FileArgument.from(lv, false, FileArgument.Reason.CREATE); + if (lv.size() < 3) + { + throw new InternalExpressionException("'write_file' requires three or more arguments"); + } + final FileArgument fdesc = FileArgument.from(lv, false, FileArgument.Reason.CREATE); - boolean success; + final boolean success; if (fdesc.type == FileArgument.Type.NBT) { - Value val = lv.get(2); - NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) - ? (NBTSerializableValue) val + final Value val = lv.get(2); + final NBTSerializableValue tagValue = (val instanceof final NBTSerializableValue nbtsv) + ? nbtsv : new NBTSerializableValue(val.getString()); - Tag tag = tagValue.getTag(); + final Tag tag = tagValue.getTag(); success = ((CarpetScriptHost) c.host).writeTagFile(tag, fdesc); } else if (fdesc.type == FileArgument.Type.JSON) { - List data = Collections.singletonList(GSON.toJson(lv.get(2).toJson())); + final List data = Collections.singletonList(GSON.toJson(lv.get(2).toJson())); ((CarpetScriptHost) c.host).removeResourceFile(fdesc); success = ((CarpetScriptHost) c.host).appendLogFile(fdesc, data); } else { - List data = new ArrayList<>(); - if (lv.size()==3) + final List data = new ArrayList<>(); + if (lv.size() == 3) { - Value val = lv.get(2); - if (val instanceof ListValue) + final Value val = lv.get(2); + if (val instanceof final ListValue list) { - List lval = ((ListValue) val).getItems(); + final List lval = list.getItems(); lval.forEach(v -> data.add(v.getString())); } else @@ -911,7 +1009,7 @@ public class Auxiliary { } else { - for(int i = 2; i < lv.size(); i++) + for (int i = 2; i < lv.size(); i++) { data.add(lv.get(i).getString()); } @@ -924,11 +1022,11 @@ public class Auxiliary { expression.addContextFunction("load_app_data", -1, (c, t, lv) -> { FileArgument fdesc = new FileArgument(null, FileArgument.Type.NBT, null, false, false, FileArgument.Reason.READ); - if (lv.size()>0) + if (lv.size() > 0) { c.host.issueDeprecation("load_app_data(...) with arguments"); - String resource = recognizeResource(lv.get(0), false); - boolean shared = lv.size() > 1 && lv.get(1).getBoolean(); + final String resource = recognizeResource(lv.get(0), false); + final boolean shared = lv.size() > 1 && lv.get(1).getBoolean(); fdesc = new FileArgument(resource, FileArgument.Type.NBT, null, false, shared, FileArgument.Reason.READ); } return NBTSerializableValue.of(((CarpetScriptHost) c.host).readFileTag(fdesc)); @@ -937,35 +1035,46 @@ public class Auxiliary { expression.addContextFunction("store_app_data", -1, (c, t, lv) -> { if (lv.size() == 0) + { throw new InternalExpressionException("'store_app_data' needs NBT tag and an optional file"); - Value val = lv.get(0); + } + final Value val = lv.get(0); FileArgument fdesc = new FileArgument(null, FileArgument.Type.NBT, null, false, false, FileArgument.Reason.CREATE); - if (lv.size()>1) + if (lv.size() > 1) { c.host.issueDeprecation("store_app_data(...) with more than one argument"); - String resource = recognizeResource(lv.get(1), false); - boolean shared = lv.size() > 2 && lv.get(2).getBoolean(); + final String resource = recognizeResource(lv.get(1), false); + final boolean shared = lv.size() > 2 && lv.get(2).getBoolean(); fdesc = new FileArgument(resource, FileArgument.Type.NBT, null, false, shared, FileArgument.Reason.CREATE); } - NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) - ? (NBTSerializableValue) val + final NBTSerializableValue tagValue = (val instanceof final NBTSerializableValue nbtsv) + ? nbtsv : new NBTSerializableValue(val.getString()); return BooleanValue.of(((CarpetScriptHost) c.host).writeTagFile(tagValue.getTag(), fdesc)); }); expression.addContextFunction("statistic", 3, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerPlayer player = EntityValue.getPlayerByValue(cc.server(), lv.get(0)); - if (player == null) return Value.NULL; - ResourceLocation category; - ResourceLocation statName; + final CarpetContext cc = (CarpetContext) c; + final ServerPlayer player = EntityValue.getPlayerByValue(cc.server(), lv.get(0)); + if (player == null) + { + return Value.NULL; + } + final ResourceLocation category; + final ResourceLocation statName; category = InputValidator.identifierOf(lv.get(1).getString()); statName = InputValidator.identifierOf(lv.get(2).getString()); - StatType type = cc.registry(Registries.STAT_TYPE).get(category); - if (type == null) return Value.NULL; - Stat stat = getStat(type, statName); - if (stat == null) return Value.NULL; + final StatType type = cc.registry(Registries.STAT_TYPE).get(category); + if (type == null) + { + return Value.NULL; + } + final Stat stat = getStat(type, statName); + if (stat == null) + { + return Value.NULL; + } return new NumericValue(player.getStats().getValue(stat)); }); @@ -973,34 +1082,49 @@ public class Auxiliary { expression.addContextFunction("handle_event", -1, (c, t, lv) -> { if (lv.size() < 2) + { throw new InternalExpressionException("'handle_event' requires at least two arguments, event name, and a callback"); - String event = lv.get(0).getString(); - FunctionArgument callback = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); - CarpetScriptHost host = ((CarpetScriptHost)c.host); + } + final String event = lv.get(0).getString(); + final FunctionArgument callback = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); + final CarpetScriptHost host = ((CarpetScriptHost) c.host); if (callback.function == null) + { return BooleanValue.of(host.scriptServer().events.removeBuiltInEvent(event, host)); + } // args don't need to be checked will be checked at the event - return BooleanValue.of( host.scriptServer().events.handleCustomEvent(event, host, callback.function, callback.args )); + return BooleanValue.of(host.scriptServer().events.handleCustomEvent(event, host, callback.function, callback.args)); }); //signal_event('event', player or null, args.... ) -> number of apps notified expression.addContextFunction("signal_event", -1, (c, t, lv) -> { if (lv.size() == 0) + { throw new InternalExpressionException("'signal' requires at least one argument"); - CarpetContext cc = (CarpetContext)c; - CarpetScriptServer server = ((CarpetScriptHost)c.host).scriptServer(); - String eventName = lv.get(0).getString(); + } + final CarpetContext cc = (CarpetContext) c; + final CarpetScriptServer server = ((CarpetScriptHost) c.host).scriptServer(); + final String eventName = lv.get(0).getString(); // no such event yet - if (CarpetEventServer.Event.getEvent(eventName, server) == null) return Value.NULL; + if (CarpetEventServer.Event.getEvent(eventName, server) == null) + { + return Value.NULL; + } ServerPlayer player = null; List args = Collections.emptyList(); if (lv.size() > 1) { player = EntityValue.getPlayerByValue(server.server, lv.get(1)); - if (lv.size() > 2) args = lv.subList(2, lv.size()); + if (lv.size() > 2) + { + args = lv.subList(2, lv.size()); + } + } + final int counts = ((CarpetScriptHost) c.host).scriptServer().events.signalEvent(eventName, cc, player, args); + if (counts < 0) + { + return Value.NULL; } - int counts = ((CarpetScriptHost)c.host).scriptServer().events.signalEvent(eventName, cc, player, args); - if (counts < 0) return Value.NULL; return new NumericValue(counts); }); @@ -1008,16 +1132,23 @@ public class Auxiliary { // nbt_storage(key) // nbt_storage(key, nbt) expression.addContextFunction("nbt_storage", -1, (c, t, lv) -> { - if (lv.size() > 2) throw new InternalExpressionException("'nbt_storage' requires 0, 1 or 2 arguments."); - CarpetContext cc = (CarpetContext) c; - CommandStorage storage = cc.server().getCommandStorage(); + if (lv.size() > 2) + { + throw new InternalExpressionException("'nbt_storage' requires 0, 1 or 2 arguments."); + } + final CarpetContext cc = (CarpetContext) c; + final CommandStorage storage = cc.server().getCommandStorage(); if (lv.size() == 0) + { return ListValue.wrap(storage.keys().map(i -> new StringValue(nameFromRegistryId(i)))); - String key = lv.get(0).getString(); - CompoundTag old_nbt = storage.get(InputValidator.identifierOf(key)); - if (lv.size() == 2) { - Value nbt = lv.get(1); - NBTSerializableValue new_nbt = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt + } + final String key = lv.get(0).getString(); + final CompoundTag old_nbt = storage.get(InputValidator.identifierOf(key)); + if (lv.size() == 2) + { + final Value nbt = lv.get(1); + final NBTSerializableValue new_nbt = (nbt instanceof final NBTSerializableValue nbtsv) + ? nbtsv : NBTSerializableValue.parseString(nbt.getString(), true); storage.set(InputValidator.identifierOf(key), new_nbt.getCompoundTag()); } @@ -1026,31 +1157,39 @@ public class Auxiliary { // script run create_datapack('foo', {'foo' -> {'bar.json' -> {'c' -> true,'d' -> false,'e' -> {'foo' -> [1,2,3]},'a' -> 'foobar','b' -> 5}}}) expression.addContextFunction("create_datapack", 2, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - String origName = lv.get(0).getString(); - String name = InputValidator.validateSimpleString(origName, true); - MinecraftServer server = cc.server(); - for (String dpName : server.getPackRepository().getAvailableIds()) + final CarpetContext cc = (CarpetContext) c; + final String origName = lv.get(0).getString(); + final String name = InputValidator.validateSimpleString(origName, true); + final MinecraftServer server = cc.server(); + for (final String dpName : server.getPackRepository().getAvailableIds()) { - if (dpName.equalsIgnoreCase("file/"+name+".zip") || - dpName.equalsIgnoreCase("file/"+name)) + if (dpName.equalsIgnoreCase("file/" + name + ".zip") || + dpName.equalsIgnoreCase("file/" + name)) + { return Value.NULL; + } } - Value dpdata = lv.get(1); - if (!(dpdata instanceof MapValue)) - throw new InternalExpressionException("datapack data needs to be a valid map type"); - PackRepository packManager = server.getPackRepository(); - Path dbFloder = server.getWorldPath(LevelResource.DATAPACK_DIR); - Path packFloder = dbFloder.resolve(name+".zip"); - if (Files.exists(packFloder) || Files.exists(dbFloder.resolve(name))) return Value.NULL; - Boolean [] successful = new Boolean[]{true}; - server.executeBlocking( () -> + final Value dpdata = lv.get(1); + if (!(dpdata instanceof final MapValue dpMap)) { - try { - //Files.createDirectory(packFloder); - try (FileSystem zipfs = FileSystems.newFileSystem(URI.create("jar:" + packFloder.toUri().toString()), Map.of("create", "true"))) { - Path zipRoot = zipfs.getPath("/"); + throw new InternalExpressionException("datapack data needs to be a valid map type"); + } + final PackRepository packManager = server.getPackRepository(); + final Path dbFloder = server.getWorldPath(LevelResource.DATAPACK_DIR); + final Path packFloder = dbFloder.resolve(name + ".zip"); + if (Files.exists(packFloder) || Files.exists(dbFloder.resolve(name))) + { + return Value.NULL; + } + final Boolean[] successful = new Boolean[]{true}; + server.executeBlocking(() -> + { + try + { + try (final FileSystem zipfs = FileSystems.newFileSystem(URI.create("jar:" + packFloder.toUri().toString()), Map.of("create", "true"))) + { + final Path zipRoot = zipfs.getPath("/"); zipValueToJson(zipRoot.resolve("pack.mcmeta"), MapValue.wrap( Map.of(StringValue.of("pack"), MapValue.wrap(Map.of( StringValue.of("pack_format"), new NumericValue(SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA)), @@ -1058,14 +1197,15 @@ public class Auxiliary { StringValue.of("source"), StringValue.of("scarpet") ))) )); - walkTheDPMap((MapValue) dpdata, zipRoot); + walkTheDPMap(dpMap, zipRoot); } packManager.reload(); - Pack resourcePackProfile = packManager.getPack("file/" + name + ".zip"); - if (resourcePackProfile == null || packManager.getSelectedPacks().contains(resourcePackProfile)) { + final Pack resourcePackProfile = packManager.getPack("file/" + name + ".zip"); + if (resourcePackProfile == null || packManager.getSelectedPacks().contains(resourcePackProfile)) + { throw new IOException(); } - List list = Lists.newArrayList(packManager.getSelectedPacks()); + final List list = Lists.newArrayList(packManager.getSelectedPacks()); resourcePackProfile.getDefaultPosition().insert(list, resourcePackProfile, p -> p, false); @@ -1074,15 +1214,20 @@ public class Auxiliary { successful[0] = false; return null; }).join(); - if (!successful[0]) { + if (!successful[0]) + { throw new IOException(); } - } catch (IOException e) + } + catch (final IOException e) { successful[0] = false; - try { + try + { PathUtils.delete(packFloder); - } catch (IOException ignored) { + } + catch (final IOException ignored) + { throw new InternalExpressionException("Failed to install a datapack and failed to clean up after it"); } @@ -1092,145 +1237,165 @@ public class Auxiliary { }); expression.addContextFunction("enable_hidden_dimensions", 0, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - cc.host.issueDeprecation("enable_hidden_dimensions in 1.18.2 and 1.19"); + final CarpetContext cc = (CarpetContext) c; + cc.host.issueDeprecation("enable_hidden_dimensions in 1.18.2 and 1.19+"); return Value.NULL; }); } - private static void zipValueToJson(Path path, Value output) throws IOException + private static void zipValueToJson(final Path path, final Value output) throws IOException { - JsonElement element = output.toJson(); + final JsonElement element = output.toJson(); if (element == null) - throw new InternalExpressionException("Cannot interpret "+output.getPrettyString()+" as a json object"); - String string = GSON.toJson(element); + { + throw new InternalExpressionException("Cannot interpret " + output.getPrettyString() + " as a json object"); + } + final String string = GSON.toJson(element); Files.createDirectories(path.getParent()); - BufferedWriter bufferedWriter = Files.newBufferedWriter(path); + final BufferedWriter bufferedWriter = Files.newBufferedWriter(path); Throwable incident = null; try { bufferedWriter.write(string); } - catch (Throwable shitHappened) + catch (final Throwable shitHappened) { incident = shitHappened; throw shitHappened; } finally { - if (incident != null) { - try { + if (incident != null) + { + try + { bufferedWriter.close(); - } catch (Throwable otherShitHappened) { + } + catch (final Throwable otherShitHappened) + { incident.addSuppressed(otherShitHappened); } - } else { + } + else + { bufferedWriter.close(); } } } - private static void zipValueToText(Path path, Value output) throws IOException + + private static void zipValueToText(final Path path, final Value output) throws IOException { - List toJoin; - String string; - String delimiter=System.lineSeparator(); + final List toJoin; + final String string; + final String delimiter = System.lineSeparator(); // i dont know it shoule be \n or System.lineSeparator - if (output instanceof LazyListValue) + if (output instanceof LazyListValue lazyListValue) { - toJoin = ((LazyListValue) output).unroll(); + toJoin = lazyListValue.unroll(); string = toJoin.stream().map(Value::getString).collect(Collectors.joining(delimiter)); } - else if (output instanceof ListValue) + else if (output instanceof ListValue listValue) { - toJoin = ((ListValue) output).getItems(); + toJoin = listValue.getItems(); string = toJoin.stream().map(Value::getString).collect(Collectors.joining(delimiter)); } else { string = output.getString(); } - - + + Files.createDirectories(path.getParent()); - BufferedWriter bufferedWriter = Files.newBufferedWriter(path); + final BufferedWriter bufferedWriter = Files.newBufferedWriter(path); Throwable incident = null; try { bufferedWriter.write(string); } - catch (Throwable shitHappened) + catch (final Throwable shitHappened) { incident = shitHappened; throw shitHappened; } finally { - if (incident != null) { - try { + if (incident != null) + { + try + { bufferedWriter.close(); - } catch (Throwable otherShitHappened) { + } + catch (final Throwable otherShitHappened) + { incident.addSuppressed(otherShitHappened); } - } else { + } + else + { bufferedWriter.close(); } } } - private static void zipValueToNBT(Path path, Value output) throws IOException + private static void zipValueToNBT(final Path path, final Value output) throws IOException { - - - NBTSerializableValue tagValue = (output instanceof NBTSerializableValue) - ? (NBTSerializableValue) output - : new NBTSerializableValue(output.getString()); - Tag tag = tagValue.getTag(); + final NBTSerializableValue tagValue = (output instanceof NBTSerializableValue nbtSerializableValue) + ? nbtSerializableValue + : new NBTSerializableValue(output.getString()); + final Tag tag = tagValue.getTag(); Files.createDirectories(path.getParent()); - - try { - if (tag instanceof CompoundTag) - NbtIo.writeCompressed((CompoundTag) tag, Files.newOutputStream(path)); + if (tag instanceof final CompoundTag cTag) + { + NbtIo.writeCompressed(cTag, Files.newOutputStream(path)); + } } - catch (Throwable shitHappened) + catch (final Throwable shitHappened) { throw shitHappened; } } - private static void walkTheDPMap(MapValue node, Path path) throws IOException + private static void walkTheDPMap(final MapValue node, final Path path) throws IOException { - Map items = node.getMap(); - for (Map.Entry entry : items.entrySet()) + final Map items = node.getMap(); + for (final Map.Entry entry : items.entrySet()) { - Value val = entry.getValue(); - String strkey = entry.getKey().getString(); - Path child = path.resolve(strkey); + final Value val = entry.getValue(); + final String strkey = entry.getKey().getString(); + final Path child = path.resolve(strkey); if (strkey.endsWith(".json")) { zipValueToJson(child, val); } - else if (strkey.endsWith(".mcfunction")|strkey.endsWith(".txt")|strkey.endsWith(".mcmeta")) + else if (strkey.endsWith(".mcfunction") || strkey.endsWith(".txt") || strkey.endsWith(".mcmeta")) { zipValueToText(child, val); - }else if (strkey.endsWith(".nbt")) + } + else if (strkey.endsWith(".nbt")) { zipValueToNBT(child, val); - }else + } + else { - if (!(val instanceof MapValue)) throw new InternalExpressionException("Value of "+strkey+" should be a map"); + if (!(val instanceof final MapValue map)) + { + throw new InternalExpressionException("Value of " + strkey + " should be a map"); + } Files.createDirectory(child); - walkTheDPMap((MapValue) val, child); + walkTheDPMap(map, child); } } } - private static Stat getStat(StatType type, ResourceLocation id) + private static Stat getStat(final StatType type, final ResourceLocation id) { - T key = type.getRegistry().get(id); + final T key = type.getRegistry().get(id); if (key == null || !type.contains(key)) + { return null; + } return type.get(key); } } diff --git a/src/main/java/carpet/script/api/BlockIterators.java b/src/main/java/carpet/script/api/BlockIterators.java index d5ee8ac6..e1716329 100644 --- a/src/main/java/carpet/script/api/BlockIterators.java +++ b/src/main/java/carpet/script/api/BlockIterators.java @@ -15,9 +15,11 @@ import carpet.script.value.LazyListValue; import carpet.script.value.ListValue; import carpet.script.value.NumericValue; import carpet.script.value.Value; + import java.util.ArrayList; import java.util.List; import java.util.Locale; + import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; import net.minecraft.server.level.ServerLevel; @@ -27,19 +29,23 @@ import static java.lang.Math.abs; import static java.lang.Math.max; import static java.lang.Math.min; -public class BlockIterators { - public static void apply(Expression expression) +public class BlockIterators +{ + public static void apply(final Expression expression) { // lazy cause of lazy expression expression.addLazyFunction("scan", (c, t, llv) -> { - if (llv.size() < 3) throw new InternalExpressionException("'scan' needs many more arguments"); - List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE); - CarpetContext cc = (CarpetContext)c; - BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0); + if (llv.size() < 3) + { + throw new InternalExpressionException("'scan' needs many more arguments"); + } + final List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size() - 1), c, Context.NONE); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0); Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset); - BlockPos center = centerLocator.block.getPos(); - Vec3i range; + final BlockPos center = centerLocator.block.getPos(); + final Vec3i range; if (rangeLocator.fromBlock) { @@ -48,14 +54,13 @@ public class BlockIterators { abs(rangeLocator.vec.y - center.getY()), abs(rangeLocator.vec.z - center.getZ()) ); - //if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression") } else { range = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); } Vec3i upperRange = range; - if (lv.size() > rangeLocator.offset+1) // +1 cause we still need the expression + if (lv.size() > rangeLocator.offset + 1) // +1 cause we still need the expression { rangeLocator = Vector3Argument.findIn(lv, rangeLocator.offset); if (rangeLocator.fromBlock) @@ -65,60 +70,60 @@ public class BlockIterators { abs(rangeLocator.vec.y - center.getY()), abs(rangeLocator.vec.z - center.getZ()) ); - //if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression") } else { upperRange = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); } } - if (llv.size() != rangeLocator.offset+1) + if (llv.size() != rangeLocator.offset + 1) { - throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: "+lv.size()+" "+rangeLocator.offset); + throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: " + lv.size() + " " + rangeLocator.offset); } - LazyValue expr = llv.get(rangeLocator.offset); + final LazyValue expr = llv.get(rangeLocator.offset); - int cx = center.getX(); - int cy = center.getY(); - int cz = center.getZ(); - int xrange = range.getX(); - int yrange = range.getY(); - int zrange = range.getZ(); - int xprange = upperRange.getX(); - int yprange = upperRange.getY(); - int zprange = upperRange.getZ(); + final int cx = center.getX(); + final int cy = center.getY(); + final int cz = center.getZ(); + final int xrange = range.getX(); + final int yrange = range.getY(); + final int zrange = range.getZ(); + final int xprange = upperRange.getX(); + final int yprange = upperRange.getY(); + final int zprange = upperRange.getZ(); //saving outer scope - LazyValue _x = c.getVariable("_x"); - LazyValue _y = c.getVariable("_y"); - LazyValue _z = c.getVariable("_z"); - LazyValue __ = c.getVariable("_"); + final LazyValue _x = c.getVariable("_x"); + final LazyValue _y = c.getVariable("_y"); + final LazyValue _z = c.getVariable("_z"); + final LazyValue __ = c.getVariable("_"); int sCount = 0; - outer:for (int y=cy-yrange; y <= cy+yprange; y++) + outer: + for (int y = cy - yrange; y <= cy + yprange; y++) { - int yFinal = y; + final int yFinal = y; c.setVariable("_y", (c_, t_) -> new NumericValue(yFinal).bindTo("_y")); - for (int x=cx-xrange; x <= cx+xprange; x++) + for (int x = cx - xrange; x <= cx + xprange; x++) { - int xFinal = x; + final int xFinal = x; c.setVariable("_x", (c_, t_) -> new NumericValue(xFinal).bindTo("_x")); - for (int z=cz-zrange; z <= cz+zprange; z++) + for (int z = cz - zrange; z <= cz + zprange; z++) { - int zFinal = z; + final int zFinal = z; c.setVariable("_z", (c_, t_) -> new NumericValue(zFinal).bindTo("_z")); - Value blockValue = BlockValue.fromCoords(((CarpetContext)c), xFinal,yFinal,zFinal).bindTo("_"); - c.setVariable( "_", (cc_, t_c) -> blockValue); + final Value blockValue = BlockValue.fromCoords(((CarpetContext) c), xFinal, yFinal, zFinal).bindTo("_"); + c.setVariable("_", (cc_, t_c) -> blockValue); Value result; try { result = expr.evalValue(c, t); } - catch (ContinueStatement notIgnored) + catch (final ContinueStatement notIgnored) { result = notIgnored.retval; } - catch (BreakStatement notIgnored) + catch (final BreakStatement notIgnored) { break outer; } @@ -134,66 +139,70 @@ public class BlockIterators { c.setVariable("_y", _y); c.setVariable("_z", _z); c.setVariable("_", __); - int finalSCount = sCount; + final int finalSCount = sCount; return (c_, t_) -> new NumericValue(finalSCount); }); // must be lazy expression.addLazyFunction("volume", (c, t, llv) -> { - CarpetContext cc = (CarpetContext)c; - if (llv.size() < 3) throw new InternalExpressionException("'volume' needs many more arguments"); - List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size()-1), c, Context.NONE); + final CarpetContext cc = (CarpetContext) c; + if (llv.size() < 3) + { + throw new InternalExpressionException("'volume' needs many more arguments"); + } + final List lv = Fluff.AbstractFunction.unpackLazy(llv.subList(0, llv.size() - 1), c, Context.NONE); - BlockArgument pos1Locator = BlockArgument.findIn(cc, lv, 0); - BlockArgument pos2Locator = BlockArgument.findIn(cc, lv, pos1Locator.offset); - BlockPos pos1 = pos1Locator.block.getPos(); - BlockPos pos2 = pos2Locator.block.getPos(); + final BlockArgument pos1Locator = BlockArgument.findIn(cc, lv, 0); + final BlockArgument pos2Locator = BlockArgument.findIn(cc, lv, pos1Locator.offset); + final BlockPos pos1 = pos1Locator.block.getPos(); + final BlockPos pos2 = pos2Locator.block.getPos(); - int x1 = pos1.getX(); - int y1 = pos1.getY(); - int z1 = pos1.getZ(); - int x2 = pos2.getX(); - int y2 = pos2.getY(); - int z2 = pos2.getZ(); - int minx = min(x1, x2); - int miny = min(y1, y2); - int minz = min(z1, z2); - int maxx = max(x1, x2); - int maxy = max(y1, y2); - int maxz = max(z1, z2); - LazyValue expr = llv.get(pos2Locator.offset); + final int x1 = pos1.getX(); + final int y1 = pos1.getY(); + final int z1 = pos1.getZ(); + final int x2 = pos2.getX(); + final int y2 = pos2.getY(); + final int z2 = pos2.getZ(); + final int minx = min(x1, x2); + final int miny = min(y1, y2); + final int minz = min(z1, z2); + final int maxx = max(x1, x2); + final int maxy = max(y1, y2); + final int maxz = max(z1, z2); + final LazyValue expr = llv.get(pos2Locator.offset); //saving outer scope - LazyValue _x = c.getVariable("_x"); - LazyValue _y = c.getVariable("_y"); - LazyValue _z = c.getVariable("_z"); - LazyValue __ = c.getVariable("_"); + final LazyValue _x = c.getVariable("_x"); + final LazyValue _y = c.getVariable("_y"); + final LazyValue _z = c.getVariable("_z"); + final LazyValue __ = c.getVariable("_"); int sCount = 0; - outer:for (int y=miny; y <= maxy; y++) + outer: + for (int y = miny; y <= maxy; y++) { - int yFinal = y; + final int yFinal = y; c.setVariable("_y", (c_, t_) -> new NumericValue(yFinal).bindTo("_y")); - for (int x=minx; x <= maxx; x++) + for (int x = minx; x <= maxx; x++) { - int xFinal = x; + final int xFinal = x; c.setVariable("_x", (c_, t_) -> new NumericValue(xFinal).bindTo("_x")); - for (int z=minz; z <= maxz; z++) + for (int z = minz; z <= maxz; z++) { - int zFinal = z; + final int zFinal = z; c.setVariable("_z", (c_, t_) -> new NumericValue(zFinal).bindTo("_z")); - Value blockValue = BlockValue.fromCoords(((CarpetContext)c), xFinal,yFinal,zFinal).bindTo("_"); - c.setVariable( "_", (cc_, t_c) -> blockValue); + final Value blockValue = BlockValue.fromCoords(((CarpetContext) c), xFinal, yFinal, zFinal).bindTo("_"); + c.setVariable("_", (cc_, t_c) -> blockValue); Value result; try { result = expr.evalValue(c, t); } - catch (ContinueStatement notIgnored) + catch (final ContinueStatement notIgnored) { result = notIgnored.retval; } - catch (BreakStatement notIgnored) + catch (final BreakStatement notIgnored) { break outer; } @@ -209,16 +218,16 @@ public class BlockIterators { c.setVariable("_y", _y); c.setVariable("_z", _z); c.setVariable("_", __); - int finalSCount = sCount; + final int finalSCount = sCount; return (c_, t_) -> new NumericValue(finalSCount); }); - expression.addContextFunction("neighbours", -1, (c, t, lv)-> + expression.addContextFunction("neighbours", -1, (c, t, lv) -> { - BlockPos center = BlockArgument.findIn((CarpetContext) c, lv,0).block.getPos(); - ServerLevel world = ((CarpetContext) c).level(); + final BlockPos center = BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos(); + final ServerLevel world = ((CarpetContext) c).level(); - List neighbours = new ArrayList<>(); + final List neighbours = new ArrayList<>(); neighbours.add(new BlockValue(null, world, center.above())); neighbours.add(new BlockValue(null, world, center.below())); neighbours.add(new BlockValue(null, world, center.north())); @@ -228,20 +237,26 @@ public class BlockIterators { return ListValue.wrap(neighbours); }); - expression.addContextFunction("rect", -1, (c, t, lv)-> + expression.addContextFunction("rect", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - int cx, cy, cz; - int sminx, sminy, sminz; - int smaxx, smaxy, smaxz; - BlockArgument cposLocator = BlockArgument.findIn(cc, lv, 0); - BlockPos cpos = cposLocator.block.getPos(); + final CarpetContext cc = (CarpetContext) c; + final int cx; + final int cy; + final int cz; + final int sminx; + final int sminy; + final int sminz; + final int smaxx; + final int smaxy; + final int smaxz; + final BlockArgument cposLocator = BlockArgument.findIn(cc, lv, 0); + final BlockPos cpos = cposLocator.block.getPos(); cx = cpos.getX(); cy = cpos.getY(); cz = cpos.getZ(); if (lv.size() > cposLocator.offset) { - Vector3Argument diffLocator = Vector3Argument.findIn(lv, cposLocator.offset); + final Vector3Argument diffLocator = Vector3Argument.findIn(lv, cposLocator.offset); if (diffLocator.fromBlock) { sminx = Mth.floor(abs(diffLocator.vec.x - cx)); @@ -256,7 +271,7 @@ public class BlockIterators { } if (lv.size() > diffLocator.offset) { - Vector3Argument posDiff = Vector3Argument.findIn(lv, diffLocator.offset); + final Vector3Argument posDiff = Vector3Argument.findIn(lv, diffLocator.offset); if (posDiff.fromBlock) { smaxx = Mth.floor(abs(posDiff.vec.x - cx)); @@ -289,19 +304,21 @@ public class BlockIterators { return new LazyListValue() { - final int minx = cx-sminx; - final int miny = cy-sminy; - final int minz = cz-sminz; - final int maxx = cx+smaxx; - final int maxy = cy+smaxy; - final int maxz = cz+smaxz; + final int minx = cx - sminx; + final int miny = cy - sminy; + final int minz = cz - sminz; + final int maxx = cx + smaxx; + final int maxy = cy + smaxy; + final int maxz = cz + smaxz; int x; int y; int z; + { reset(); } + @Override public boolean hasNext() { @@ -311,7 +328,7 @@ public class BlockIterators { @Override public Value next() { - Value r = BlockValue.fromCoords(cc, x,y,z); + final Value r = BlockValue.fromCoords(cc, x, y, z); //possibly reroll context x++; if (x > maxx) @@ -347,56 +364,57 @@ public class BlockIterators { @Override public String getString() { - return String.format(Locale.ROOT, "rect[(%d,%d,%d),..,(%d,%d,%d)]",minx, miny, minz, maxx, maxy, maxz); + return String.format(Locale.ROOT, "rect[(%d,%d,%d),..,(%d,%d,%d)]", minx, miny, minz, maxx, maxy, maxz); } }; }); - expression.addContextFunction("diamond", -1, (c, t, lv)-> + expression.addContextFunction("diamond", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; + final CarpetContext cc = (CarpetContext) c; - BlockArgument cposLocator=BlockArgument.findIn((CarpetContext)c,lv,0); - BlockPos cpos = cposLocator.block.getPos(); + final BlockArgument cposLocator = BlockArgument.findIn((CarpetContext) c, lv, 0); + final BlockPos cpos = cposLocator.block.getPos(); - int cx; - int cy; - int cz; - int width; - int height; + final int cx; + final int cy; + final int cz; + final int width; + final int height; try { cx = cpos.getX(); cy = cpos.getY(); cz = cpos.getZ(); - if (lv.size()==cposLocator.offset) + if (lv.size() == cposLocator.offset) { - Value retval = ListValue.of( - BlockValue.fromCoords(cc, cx, cy-1, cz), + return ListValue.of( + BlockValue.fromCoords(cc, cx, cy - 1, cz), BlockValue.fromCoords(cc, cx, cy, cz), - BlockValue.fromCoords(cc, cx-1, cy, cz), - BlockValue.fromCoords(cc, cx, cy, cz-1), - BlockValue.fromCoords(cc, cx+1, cy, cz), - BlockValue.fromCoords(cc, cx, cy, cz+1), - BlockValue.fromCoords(cc, cx, cy+1, cz) + BlockValue.fromCoords(cc, cx - 1, cy, cz), + BlockValue.fromCoords(cc, cx, cy, cz - 1), + BlockValue.fromCoords(cc, cx + 1, cy, cz), + BlockValue.fromCoords(cc, cx, cy, cz + 1), + BlockValue.fromCoords(cc, cx, cy + 1, cz) ); - return retval; } - else if (lv.size()==1+cposLocator.offset) + else if (lv.size() == 1 + cposLocator.offset) { width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong(); height = 0; } - else if(lv.size()==2+cposLocator.offset) + else if (lv.size() == 2 + cposLocator.offset) { width = (int) ((NumericValue) lv.get(cposLocator.offset)).getLong(); - height = (int) ((NumericValue) lv.get(cposLocator.offset+1)).getLong(); - } else{ + height = (int) ((NumericValue) lv.get(cposLocator.offset + 1)).getLong(); + } + else + { throw new InternalExpressionException("Incorrect number of arguments for 'diamond'"); } } - catch (ClassCastException exc) + catch (final ClassCastException ignored) { throw new InternalExpressionException("Attempted to pass a non-number to 'diamond'"); } @@ -406,9 +424,11 @@ public class BlockIterators { { int curradius; int curpos; + { reset(); } + @Override public boolean hasNext() { @@ -425,9 +445,9 @@ public class BlockIterators { } // x = 3-|i-6| // z = |( (i-3)%12-6|-3 - Value block = BlockValue.fromCoords(cc, cx+(curradius-abs(curpos-2*curradius)), cy, cz-curradius+abs( abs(curpos-curradius)%(4*curradius) -2*curradius )); + final Value block = BlockValue.fromCoords(cc, cx + (curradius - abs(curpos - 2 * curradius)), cy, cz - curradius + abs(abs(curpos - curradius) % (4 * curradius) - 2 * curradius)); curpos++; - if (curpos>=curradius*4) + if (curpos >= curradius * 4) { curradius++; curpos = 0; @@ -446,7 +466,7 @@ public class BlockIterators { @Override public String getString() { - return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,0]",cx, cy, cz, width); + return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,0]", cx, cy, cz, width); } }; } @@ -457,9 +477,11 @@ public class BlockIterators { int curradius; int curpos; int curheight; + { reset(); } + @Override public boolean hasNext() { @@ -471,27 +493,26 @@ public class BlockIterators { { if (curheight == -height || curheight == height) { - return BlockValue.fromCoords(cc, cx, cy+curheight++, cz); + return BlockValue.fromCoords(cc, cx, cy + curheight++, cz); } if (curradius == 0) { curradius++; - return BlockValue.fromCoords(cc, cx, cy+curheight, cz); + return BlockValue.fromCoords(cc, cx, cy + curheight, cz); } // x = 3-|i-6| // z = |( (i-3)%12-6|-3 - Value block = BlockValue.fromCoords(cc, cx+(curradius-abs(curpos-2*curradius)), cy+curheight, cz-curradius+abs( abs(curpos-curradius)%(4*curradius) -2*curradius )); + final Value block = BlockValue.fromCoords(cc, cx + (curradius - abs(curpos - 2 * curradius)), cy + curheight, cz - curradius + abs(abs(curpos - curradius) % (4 * curradius) - 2 * curradius)); curpos++; - if (curpos>=curradius*4) + if (curpos >= curradius * 4) { curradius++; curpos = 0; - if (curradius>width -abs(width*curheight/height)) + if (curradius > width - abs(width * curheight / height)) { curheight++; curradius = 0; - curpos = 0; } } return block; @@ -508,7 +529,7 @@ public class BlockIterators { @Override public String getString() { - return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,%d]",cx, cy, cz, width, height); + return String.format(Locale.ROOT, "diamond[(%d,%d,%d),%d,%d]", cx, cy, cz, width, height); } }; } diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index 00b6036c..ed917f2e 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -15,6 +15,7 @@ import carpet.script.value.NumericValue; import carpet.script.value.Value; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -23,6 +24,7 @@ import java.util.Locale; import java.util.Set; import java.util.UUID; import java.util.function.Predicate; + import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; @@ -38,159 +40,183 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; -public class Entities { - private static ListValue getPlayersFromWorldMatching(Context c, Predicate condition) { - List ret = new ArrayList<>(); - for (ServerPlayer player: ((CarpetContext) c).level().players()) { - if (condition.test(player)) { +public class Entities +{ + private static ListValue getPlayersFromWorldMatching(final Context c, final Predicate condition) + { + final List ret = new ArrayList<>(); + for (final ServerPlayer player : ((CarpetContext) c).level().players()) + { + if (condition.test(player)) + { ret.add(new EntityValue(player)); } } return ListValue.wrap(ret); } - public static void apply(Expression expression) + public static void apply(final Expression expression) { expression.addContextFunction("player", -1, (c, t, lv) -> { if (lv.size() == 0) { - CarpetContext cc = (CarpetContext)c; + final CarpetContext cc = (CarpetContext) c; if (cc.host.user != null) { - ServerPlayer player = cc.server().getPlayerList().getPlayerByName(cc.host.user); + final ServerPlayer player = cc.server().getPlayerList().getPlayerByName(cc.host.user); return EntityValue.of(player); } - Entity callingEntity = cc.source().getEntity(); - if (callingEntity instanceof Player) return EntityValue.of(callingEntity); - Vec3 pos = ((CarpetContext)c).source().getPosition(); - Player closestPlayer = ((CarpetContext)c).level().getNearestPlayer(pos.x, pos.y, pos.z, -1.0, EntitySelector.ENTITY_STILL_ALIVE); + final Entity callingEntity = cc.source().getEntity(); + if (callingEntity instanceof Player) + { + return EntityValue.of(callingEntity); + } + final Vec3 pos = ((CarpetContext) c).source().getPosition(); + final Player closestPlayer = ((CarpetContext) c).level().getNearestPlayer(pos.x, pos.y, pos.z, -1.0, EntitySelector.ENTITY_STILL_ALIVE); return EntityValue.of(closestPlayer); } - String playerName = lv.get(0).getString(); - return switch (playerName) { - case "all" -> { - List ret = new ArrayList<>(); - for (ServerPlayer player: ((CarpetContext)c).server().getPlayerList().getPlayers()) - ret.add(new EntityValue(player)); - yield ListValue.wrap(ret); - } - case "*" -> getPlayersFromWorldMatching(c, p -> true); - case "survival" -> getPlayersFromWorldMatching(c, p -> p.gameMode.isSurvival()); // todo assert correct - case "creative" -> getPlayersFromWorldMatching(c, ServerPlayer::isCreative); - case "spectating" -> getPlayersFromWorldMatching(c, ServerPlayer::isSpectator); - case "!spectating" -> getPlayersFromWorldMatching(c, p -> !p.isSpectator()); - default -> { - ServerPlayer player = ((CarpetContext) c).server().getPlayerList().getPlayerByName(playerName); - if (player != null) { - yield new EntityValue(player); - } - yield Value.NULL; - } - }; + final String playerName = lv.get(0).getString(); + return switch (playerName) + { + case "all" -> { + final List ret = new ArrayList<>(); + for (final ServerPlayer player : ((CarpetContext) c).server().getPlayerList().getPlayers()) + { + ret.add(new EntityValue(player)); + } + yield ListValue.wrap(ret); + } + case "*" -> getPlayersFromWorldMatching(c, p -> true); + case "survival" -> getPlayersFromWorldMatching(c, p -> p.gameMode.isSurvival()); // todo assert correct + case "creative" -> getPlayersFromWorldMatching(c, ServerPlayer::isCreative); + case "spectating" -> getPlayersFromWorldMatching(c, ServerPlayer::isSpectator); + case "!spectating" -> getPlayersFromWorldMatching(c, p -> !p.isSpectator()); + default -> { + final ServerPlayer player = ((CarpetContext) c).server().getPlayerList().getPlayerByName(playerName); + yield player != null ? new EntityValue(player) : Value.NULL; + } + }; }); expression.addContextFunction("spawn", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; + final CarpetContext cc = (CarpetContext) c; if (lv.size() < 2) + { throw new InternalExpressionException("'spawn' function takes mob name, and position to spawn"); - String entityString = lv.get(0).getString(); - ResourceLocation entityId; + } + final String entityString = lv.get(0).getString(); + final ResourceLocation entityId; try { entityId = ResourceLocation.read(new StringReader(entityString)); - EntityType type = cc.registry(Registries.ENTITY_TYPE).getOptional(entityId).orElse(null); + final EntityType type = cc.registry(Registries.ENTITY_TYPE).getOptional(entityId).orElse(null); if (type == null || !type.canSummon()) + { return Value.NULL; + } } - catch (CommandSyntaxException exception) + catch (final CommandSyntaxException ignored) { - return Value.NULL; + return Value.NULL; } - Vector3Argument position = Vector3Argument.findIn(lv, 1); + final Vector3Argument position = Vector3Argument.findIn(lv, 1); if (position.fromBlock) + { position.vec = position.vec.subtract(0, 0.5, 0); + } CompoundTag tag = new CompoundTag(); boolean hasTag = false; if (lv.size() > position.offset) { - Value nbt = lv.get(position.offset); - NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt + final Value nbt = lv.get(position.offset); + final NBTSerializableValue v = (nbt instanceof final NBTSerializableValue nbtsv) + ? nbtsv : NBTSerializableValue.parseString(nbt.getString(), true); hasTag = true; tag = v.getCompoundTag(); - } tag.putString("id", entityId.toString()); - Vec3 vec3d = position.vec; + final Vec3 vec3d = position.vec; - ServerLevel serverWorld = cc.level(); - Entity entity_1 = EntityType.loadEntityRecursive(tag, serverWorld, (entity_1x) -> { - entity_1x.moveTo(vec3d.x, vec3d.y, vec3d.z, entity_1x.getYRot(), entity_1x.getXRot()); - return !serverWorld.addWithUUID(entity_1x) ? null : entity_1x; + final ServerLevel serverWorld = cc.level(); + final Entity entity = EntityType.loadEntityRecursive(tag, serverWorld, e -> { + e.moveTo(vec3d.x, vec3d.y, vec3d.z, e.getYRot(), e.getXRot()); + return !serverWorld.addWithUUID(e) ? null : e; }); - if (entity_1 == null) { + if (entity == null) + { return Value.NULL; - } else { - if (!hasTag && entity_1 instanceof Mob) { - ((Mob)entity_1).finalizeSpawn(serverWorld, serverWorld.getCurrentDifficultyAt(entity_1.blockPosition()), MobSpawnType.COMMAND, null, null); - } - return new EntityValue(entity_1); } + if (!hasTag && entity instanceof final Mob mob) + { + mob.finalizeSpawn(serverWorld, serverWorld.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, null, null); + } + return new EntityValue(entity); }); expression.addContextFunction("entity_id", 1, (c, t, lv) -> { - Value who = lv.get(0); - if (who instanceof NumericValue) - return EntityValue.of(((CarpetContext)c).level().getEntity((int)((NumericValue) who).getLong())); - return EntityValue.of(((CarpetContext)c).level().getEntity(UUID.fromString(who.getString()))); + final Value who = lv.get(0); + if (who instanceof final NumericValue numericValue) + { + return EntityValue.of(((CarpetContext) c).level().getEntity((int) numericValue.getLong())); + } + return EntityValue.of(((CarpetContext) c).level().getEntity(UUID.fromString(who.getString()))); }); expression.addContextFunction("entity_list", 1, (c, t, lv) -> { - String who = lv.get(0).getString(); - CommandSourceStack source = ((CarpetContext)c).source(); - EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getServer()); - List entityList = source.getLevel().getEntities(eDesc.directType, eDesc.filteringPredicate); + final String who = lv.get(0).getString(); + final CommandSourceStack source = ((CarpetContext) c).source(); + final EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getServer()); + final List entityList = source.getLevel().getEntities(eDesc.directType, eDesc.filteringPredicate); return ListValue.wrap(entityList.stream().map(EntityValue::new)); }); expression.addContextFunction("entity_area", -1, (c, t, lv) -> { - if (lv.size()<3) throw new InternalExpressionException("'entity_area' requires entity type, center and range arguments"); - String who = lv.get(0).getString(); - CarpetContext cc = (CarpetContext)c; - Vector3Argument centerLocator = Vector3Argument.findIn(lv, 1, false, true); + if (lv.size() < 3) + { + throw new InternalExpressionException("'entity_area' requires entity type, center and range arguments"); + } + final String who = lv.get(0).getString(); + final CarpetContext cc = (CarpetContext) c; + final Vector3Argument centerLocator = Vector3Argument.findIn(lv, 1, false, true); - AABB centerBox; + final AABB centerBox; if (centerLocator.entity != null) { centerBox = centerLocator.entity.getBoundingBox(); } else { - Vec3 center = centerLocator.vec; - if (centerLocator.fromBlock) center.add(0.5, 0.5, 0.5); + final Vec3 center = centerLocator.vec; + if (centerLocator.fromBlock) + { + center.add(0.5, 0.5, 0.5); + } centerBox = new AABB(center, center); } - Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset); + final Vector3Argument rangeLocator = Vector3Argument.findIn(lv, centerLocator.offset); if (rangeLocator.fromBlock) + { throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument"); - Vec3 range = rangeLocator.vec; - AABB area = centerBox.inflate(range.x, range.y, range.z); - EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.server()); - List entityList = cc.level().getEntities(eDesc.directType, area,eDesc.filteringPredicate); + } + final Vec3 range = rangeLocator.vec; + final AABB area = centerBox.inflate(range.x, range.y, range.z); + final EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.server()); + final List entityList = cc.level().getEntities(eDesc.directType, area, eDesc.filteringPredicate); return ListValue.wrap(entityList.stream().map(EntityValue::new)); }); expression.addContextFunction("entity_selector", -1, (c, t, lv) -> { - String selector = lv.get(0).getString(); - List retlist = new ArrayList<>(); - for (Entity e: EntityValue.getEntitiesFromSelector(((CarpetContext)c).source(), selector)) + final String selector = lv.get(0).getString(); + final List retlist = new ArrayList<>(); + for (final Entity e : EntityValue.getEntitiesFromSelector(((CarpetContext) c).source(), selector)) { retlist.add(new EntityValue(e)); } @@ -199,64 +225,74 @@ public class Entities { expression.addContextFunction("query", -1, (c, t, lv) -> { - if (lv.size()<2) + if (lv.size() < 2) { throw new InternalExpressionException("'query' takes entity as a first argument, and queried feature as a second"); } - Value v = lv.get(0); - if (!(v instanceof EntityValue)) + final Value v = lv.get(0); + if (!(v instanceof final EntityValue ev)) + { throw new InternalExpressionException("First argument to query should be an entity"); - String what = lv.get(1).getString().toLowerCase(Locale.ROOT); + } + final String what = lv.get(1).getString().toLowerCase(Locale.ROOT); if (what.equals("tags")) + { c.host.issueDeprecation("'tags' for entity querying"); - Value retval; - if (lv.size()==2) - retval = ((EntityValue) v).get(what, null); - else if (lv.size()==3) - retval = ((EntityValue) v).get(what, lv.get(2)); - else - retval = ((EntityValue) v).get(what, ListValue.wrap(lv.subList(2, lv.size()))); - return retval; + } + return switch (lv.size()) + { + case 2 -> ev.get(what, null); + case 3 -> ev.get(what, lv.get(2)); + default -> ev.get(what, ListValue.wrap(lv.subList(2, lv.size()))); + }; }); // or update expression.addContextFunction("modify", -1, (c, t, lv) -> { - if (lv.size()<2) + if (lv.size() < 2) { throw new InternalExpressionException("'modify' takes entity as a first argument, and queried feature as a second"); } - Value v = lv.get(0); - if (!(v instanceof EntityValue)) + final Value v = lv.get(0); + if (!(v instanceof final EntityValue ev)) + { throw new InternalExpressionException("First argument to modify should be an entity"); - String what = lv.get(1).getString(); - if (lv.size()==2) - ((EntityValue) v).set(what, null); - else if (lv.size()==3) - ((EntityValue) v).set(what, lv.get(2)); - else - ((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size()))); + } + final String what = lv.get(1).getString(); + switch (lv.size()) + { + case 2 -> ev.set(what, null); + case 3 -> ev.set(what, lv.get(2)); + default -> ev.set(what, ListValue.wrap(lv.subList(2, lv.size()))); + } return v; }); expression.addContextFunction("entity_types", -1, (c, t, lv) -> { - if (lv.size() > 1) throw new InternalExpressionException("'entity_types' requires one or no arguments"); - String desc = (lv.size() == 1)?lv.get(0).getString():"*"; - return EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).server()).listValue(((CarpetContext)c).registryAccess()); + if (lv.size() > 1) + { + throw new InternalExpressionException("'entity_types' requires one or no arguments"); + } + final String desc = (lv.size() == 1) ? lv.get(0).getString() : "*"; + return EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).server()).listValue(((CarpetContext) c).registryAccess()); }); expression.addContextFunction("entity_load_handler", -1, (c, t, lv) -> { - if (lv.size() < 2) throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call"); - Value entityValue = lv.get(0); - List descriptors = (entityValue instanceof ListValue) - ? ((ListValue) entityValue).getItems().stream().map(Value::getString).toList() + if (lv.size() < 2) + { + throw new InternalExpressionException("'entity_load_handler' required the entity type, and a function to call"); + } + final Value entityValue = lv.get(0); + final List descriptors = (entityValue instanceof final ListValue list) + ? list.getItems().stream().map(Value::getString).toList() : Collections.singletonList(entityValue.getString()); - Set> types = new HashSet<>(); + final Set> types = new HashSet<>(); descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s, ((CarpetContext) c).server()).types)); - FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); - CarpetEventServer events = ((CarpetScriptHost)c.host).scriptServer().events; + final FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); + final CarpetEventServer events = ((CarpetScriptHost) c.host).scriptServer().events; if (funArg.function == null) { types.forEach(et -> events.removeBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), (CarpetScriptHost) c.host)); @@ -265,8 +301,8 @@ public class Entities { else { ///compat - int argno = funArg.function.getArguments().size() - funArg.args.size(); - if (argno == 1) + final int numberOfArguments = funArg.function.getArguments().size() - funArg.args.size(); + if (numberOfArguments == 1) { c.host.issueDeprecation("entity_load_handler() with single argument callback"); types.forEach(et -> events.addBuiltInEvent(CarpetEventServer.Event.getEntityLoadEventName(et), c.host, funArg.function, funArg.args)); @@ -282,16 +318,20 @@ public class Entities { // or update expression.addContextFunction("entity_event", -1, (c, t, lv) -> { - if (lv.size()<3) + if (lv.size() < 3) + { throw new InternalExpressionException("'entity_event' requires at least 3 arguments, entity, event to be handled, and function name, with optional arguments"); - Value v = lv.get(0); - if (!(v instanceof EntityValue)) + } + final Value v = lv.get(0); + if (!(v instanceof final EntityValue ev)) + { throw new InternalExpressionException("First argument to entity_event should be an entity"); - String what = lv.get(1).getString(); + } + final String what = lv.get(1).getString(); - FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); + final FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 2, true, false); - ((EntityValue) v).setEvent((CarpetContext)c, what, funArg.function, funArg.args); + ev.setEvent((CarpetContext) c, what, funArg.function, funArg.args); return Value.NULL; }); diff --git a/src/main/java/carpet/script/api/Inventories.java b/src/main/java/carpet/script/api/Inventories.java index 055f2ae2..93450aea 100644 --- a/src/main/java/carpet/script/api/Inventories.java +++ b/src/main/java/carpet/script/api/Inventories.java @@ -21,11 +21,13 @@ import carpet.script.value.StringValue; import carpet.script.value.Value; import carpet.script.value.ValueConversions; import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.Set; + import net.minecraft.commands.arguments.item.ItemInput; import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; @@ -51,129 +53,110 @@ import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.item.crafting.SingleItemRecipe; import net.minecraft.world.phys.Vec3; -public class Inventories { - public static void apply(Expression expression) +public class Inventories +{ + public static void apply(final Expression expression) { expression.addContextFunction("stack_limit", 1, (c, t, lv) -> - new NumericValue(NBTSerializableValue.parseItem(lv.get(0).getString(), ((CarpetContext) c).registryAccess() ).getItem().getMaxStackSize())); + new NumericValue(NBTSerializableValue.parseItem(lv.get(0).getString(), ((CarpetContext) c).registryAccess()).getItem().getMaxStackSize())); expression.addContextFunction("item_category", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - cc.host.issueDeprecation("item_category in 1.19.3+"); + c.host.issueDeprecation("item_category in 1.19.3+"); return Value.NULL; }); expression.addContextFunction("item_list", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - Registry items = cc.registry(Registries.ITEM); + final CarpetContext cc = (CarpetContext) c; + final Registry items = cc.registry(Registries.ITEM); if (lv.size() == 0) + { return ListValue.wrap(items.keySet().stream().map(ValueConversions::of)); - String tag = lv.get(0).getString(); - Optional> itemTag = items.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); - if (itemTag.isEmpty()) return Value.NULL; - return ListValue.wrap(itemTag.get().stream().map(b -> ValueConversions.of(items.getKey(b.value())))); - /* - TagContainer tagManager = cc.s.getServer(). getTags(); - String tag = lv.get(0).getString(); - net.minecraft.tags.Tag itemTag = tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getTag(InputValidator.identifierOf(tag)); - if (itemTag == null) return Value.NULL; - return ListValue.wrap(itemTag.getValues().stream().map(b -> ValueConversions.of(Registry.ITEM.getKey(b)))); - */ + } + final String tag = lv.get(0).getString(); + final Optional> itemTag = items.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); + return itemTag.isEmpty() ? Value.NULL : ListValue.wrap(itemTag.get().stream().map(b -> ValueConversions.of(items.getKey(b.value())))); }); expression.addContextFunction("item_tags", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; + final CarpetContext cc = (CarpetContext) c; - Registry blocks = cc.registry(Registries.ITEM); + final Registry blocks = cc.registry(Registries.ITEM); if (lv.size() == 0) + { return ListValue.wrap(blocks.getTagNames().map(ValueConversions::of)); - Item item = NBTSerializableValue.parseItem(lv.get(0).getString(), cc.registryAccess()).getItem(); + } + final Item item = NBTSerializableValue.parseItem(lv.get(0).getString(), cc.registryAccess()).getItem(); if (lv.size() == 1) { - return ListValue.wrap( blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == item))).map(e -> ValueConversions.of(e.getFirst()))); + return ListValue.wrap(blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == item))).map(e -> ValueConversions.of(e.getFirst()))); } - String tag = lv.get(1).getString(); - Optional> tagSet = blocks.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); - if (tagSet.isEmpty()) return Value.NULL; - - //return BooleanValue.of(tagSet.get().contains(item.builtInRegistryHolder())); - return BooleanValue.of(tagSet.get().stream().anyMatch(h -> h.value() == item)); - - /* - TagContainer tagManager = cc.s.getServer().getTags(); - if (lv.size() == 0) - return ListValue.wrap(tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getAvailableTags().stream().map(ValueConversions::of)); - Item item = NBTSerializableValue.parseItem(lv.get(0).getString()).getItem(); - if (lv.size() == 1) - return ListValue.wrap(tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getAllTags().entrySet().stream().filter(e -> e.getValue().contains(item)).map(e -> ValueConversions.of(e.getKey()))); - String tag = lv.get(1).getString(); - net.minecraft.tags.Tag itemTag = tagManager.getOrEmpty(Registry.ITEM_REGISTRY).getTag(InputValidator.identifierOf(tag)); - if (itemTag == null) return Value.NULL; - return BooleanValue.of(itemTag.contains(item)); - */ + final String tag = lv.get(1).getString(); + final Optional> tagSet = blocks.getTag(TagKey.create(Registries.ITEM, InputValidator.identifierOf(tag))); + return tagSet.isEmpty() ? Value.NULL : BooleanValue.of(tagSet.get().stream().anyMatch(h -> h.value() == item)); }); expression.addContextFunction("recipe_data", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - if (lv.size() < 1) throw new InternalExpressionException("'recipe_data' requires at least one argument"); - String recipeName = lv.get(0).getString(); + final CarpetContext cc = (CarpetContext) c; + if (lv.size() < 1) + { + throw new InternalExpressionException("'recipe_data' requires at least one argument"); + } + final String recipeName = lv.get(0).getString(); RecipeType type = RecipeType.CRAFTING; if (lv.size() > 1) { - String recipeType = lv.get(1).getString(); + final String recipeType = lv.get(1).getString(); type = cc.registry(Registries.RECIPE_TYPE).get(InputValidator.identifierOf(recipeType)); } - List> recipes; - recipes = ((RecipeManagerInterface) cc.server().getRecipeManager()).getAllMatching(type, InputValidator.identifierOf(recipeName), cc.registryAccess()); + final List> recipes = ((RecipeManagerInterface) cc.server().getRecipeManager()).getAllMatching(type, InputValidator.identifierOf(recipeName), cc.registryAccess()); if (recipes.isEmpty()) - return Value.NULL; - List recipesOutput = new ArrayList<>(); - RegistryAccess regs = cc.registryAccess(); - for (Recipe recipe: recipes) { - ItemStack result = recipe.getResultItem(regs); - List ingredientValue = new ArrayList<>(); - recipe.getIngredients().forEach( - ingredient -> - { - // I am flattening ingredient lists per slot. - // consider recipe_data('wooden_sword','crafting') and ('iron_nugget', 'blasting') and notice difference - // in depths of lists. - List> stacks = ((IngredientInterface) (Object) ingredient).getRecipeStacks(); - if (stacks.isEmpty()) - { - ingredientValue.add(Value.NULL); - } - else - { - List alternatives = new ArrayList<>(); - stacks.forEach(col -> col.stream().map(is -> ValueConversions.of(is, regs)).forEach(alternatives::add)); - ingredientValue.add(ListValue.wrap(alternatives)); - } - } - ); - Value recipeSpec; - if (recipe instanceof ShapedRecipe) + return Value.NULL; + } + final List recipesOutput = new ArrayList<>(); + final RegistryAccess regs = cc.registryAccess(); + for (final Recipe recipe : recipes) + { + final ItemStack result = recipe.getResultItem(regs); + final List ingredientValue = new ArrayList<>(); + recipe.getIngredients().forEach( ingredient -> { + // I am flattening ingredient lists per slot. + // consider recipe_data('wooden_sword','crafting') and ('iron_nugget', 'blasting') and notice difference + // in depths of lists. + final List> stacks = ((IngredientInterface) (Object) ingredient).getRecipeStacks(); + if (stacks.isEmpty()) + { + ingredientValue.add(Value.NULL); + } + else + { + final List alternatives = new ArrayList<>(); + stacks.forEach(col -> col.stream().map(is -> ValueConversions.of(is, regs)).forEach(alternatives::add)); + ingredientValue.add(ListValue.wrap(alternatives)); + } + }); + final Value recipeSpec; + if (recipe instanceof final ShapedRecipe shapedRecipe) { recipeSpec = ListValue.of( new StringValue("shaped"), - new NumericValue(((ShapedRecipe) recipe).getWidth()), - new NumericValue(((ShapedRecipe) recipe).getHeight()) + new NumericValue(shapedRecipe.getWidth()), + new NumericValue(shapedRecipe.getHeight()) ); } else if (recipe instanceof ShapelessRecipe) { recipeSpec = ListValue.of(new StringValue("shapeless")); } - else if (recipe instanceof AbstractCookingRecipe) + else if (recipe instanceof final AbstractCookingRecipe abstractCookingRecipe) { recipeSpec = ListValue.of( new StringValue("smelting"), - new NumericValue(((AbstractCookingRecipe) recipe).getCookingTime()), - new NumericValue(((AbstractCookingRecipe) recipe).getExperience()) + new NumericValue(abstractCookingRecipe.getCookingTime()), + new NumericValue(abstractCookingRecipe.getExperience()) ); } else if (recipe instanceof SingleItemRecipe) @@ -196,100 +179,117 @@ public class Inventories { expression.addContextFunction("crafting_remaining_item", 1, (c, t, v) -> { - String itemStr = v.get(0).getString(); - Item item; - ResourceLocation id = InputValidator.identifierOf(itemStr); - Registry registry = ((CarpetContext)c).registry(Registries.ITEM); - item = registry.getOptional(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM)); - if (!item.hasCraftingRemainingItem()) return Value.NULL; - return new StringValue(NBTSerializableValue.nameFromRegistryId(registry.getKey(item.getCraftingRemainingItem()))); + final String itemStr = v.get(0).getString(); + final ResourceLocation id = InputValidator.identifierOf(itemStr); + final Registry registry = ((CarpetContext) c).registry(Registries.ITEM); + final Item item = registry.getOptional(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM)); + return !item.hasCraftingRemainingItem() + ? Value.NULL + : new StringValue(NBTSerializableValue.nameFromRegistryId(registry.getKey(item.getCraftingRemainingItem()))); }); expression.addContextFunction("inventory_size", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) return Value.NULL; - return new NumericValue(inventoryLocator.inventory().getContainerSize()); + final CarpetContext cc = (CarpetContext) c; + final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); + return inventoryLocator == null ? Value.NULL : new NumericValue(inventoryLocator.inventory().getContainerSize()); }); expression.addContextFunction("inventory_has_items", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) return Value.NULL; - return BooleanValue.of(!inventoryLocator.inventory().isEmpty()); + final CarpetContext cc = (CarpetContext) c; + final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); + return inventoryLocator == null ? Value.NULL : BooleanValue.of(!inventoryLocator.inventory().isEmpty()); }); //inventory_get(, ) -> item_triple expression.addContextFunction("inventory_get", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) return Value.NULL; - RegistryAccess regs = cc.registryAccess(); + final CarpetContext cc = (CarpetContext) c; + final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); + if (inventoryLocator == null) + { + return Value.NULL; + } + final RegistryAccess regs = cc.registryAccess(); if (lv.size() == inventoryLocator.offset()) { - List fullInventory = new ArrayList<>(); + final List fullInventory = new ArrayList<>(); for (int i = 0, maxi = inventoryLocator.inventory().getContainerSize(); i < maxi; i++) + { fullInventory.add(ValueConversions.of(inventoryLocator.inventory().getItem(i), regs)); + } return ListValue.wrap(fullInventory); } - int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong(); + int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory()); - if (slot == inventoryLocator.inventory().getContainerSize()) return Value.NULL; - return ValueConversions.of(inventoryLocator.inventory().getItem(slot), regs); + return slot == inventoryLocator.inventory().getContainerSize() + ? Value.NULL + : ValueConversions.of(inventoryLocator.inventory().getItem(slot), regs); }); //inventory_set(, , , , ) expression.addContextFunction("inventory_set", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) return Value.NULL; - if (lv.size() < inventoryLocator.offset()+2) + final CarpetContext cc = (CarpetContext) c; + final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); + if (inventoryLocator == null) + { + return Value.NULL; + } + if (lv.size() < inventoryLocator.offset() + 2) + { throw new InternalExpressionException("'inventory_set' requires at least slot number and new stack size, and optional new item"); - int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset()+0)).getLong(); + } + int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 0)).getLong(); slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory()); - if (slot == inventoryLocator.inventory().getContainerSize()) return Value.NULL; - int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong(); - RegistryAccess regs = cc.registryAccess(); + if (slot == inventoryLocator.inventory().getContainerSize()) + { + return Value.NULL; + } + final int count = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong(); + final RegistryAccess regs = cc.registryAccess(); if (count == 0) { // clear slot - ItemStack removedStack = inventoryLocator.inventory().removeItemNoUpdate(slot); + final ItemStack removedStack = inventoryLocator.inventory().removeItemNoUpdate(slot); syncPlayerInventory(inventoryLocator, slot); - //Value res = ListValue.fromItemStack(removedStack); // that tuple will be read only but cheaper if noone cares return ValueConversions.of(removedStack, regs); } - if (lv.size() < inventoryLocator.offset()+3) + if (lv.size() < inventoryLocator.offset() + 3) { - ItemStack previousStack = inventoryLocator.inventory().getItem(slot); - ItemStack newStack = previousStack.copy(); + final ItemStack previousStack = inventoryLocator.inventory().getItem(slot); + final ItemStack newStack = previousStack.copy(); newStack.setCount(count); inventoryLocator.inventory().setItem(slot, newStack); syncPlayerInventory(inventoryLocator, slot); return ValueConversions.of(previousStack, regs); } CompoundTag nbt = null; // skipping one argument - if (lv.size() > inventoryLocator.offset()+3) + if (lv.size() > inventoryLocator.offset() + 3) { - Value nbtValue = lv.get(inventoryLocator.offset()+3); - if (nbtValue instanceof NBTSerializableValue) - nbt = ((NBTSerializableValue)nbtValue).getCompoundTag(); + final Value nbtValue = lv.get(inventoryLocator.offset() + 3); + if (nbtValue instanceof final NBTSerializableValue nbtsv) + { + nbt = nbtsv.getCompoundTag(); + } else if (nbtValue.isNull()) + { nbt = null; + } else + { nbt = new NBTSerializableValue(nbtValue.getString()).getCompoundTag(); + } } - ItemInput newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()+2).getString(), nbt, cc.registryAccess()); - ItemStack previousStack = inventoryLocator.inventory().getItem(slot); + final ItemInput newitem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset() + 2).getString(), nbt, cc.registryAccess()); + final ItemStack previousStack = inventoryLocator.inventory().getItem(slot); try { inventoryLocator.inventory().setItem(slot, newitem.createItemStack(count, false)); syncPlayerInventory(inventoryLocator, slot); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { throw new InternalExpressionException(e.getMessage()); } @@ -299,27 +299,34 @@ public class Inventories { //inventory_find(, or null (first empty slot), ) -> or null expression.addContextFunction("inventory_find", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) return Value.NULL; + final CarpetContext cc = (CarpetContext) c; + final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); + if (inventoryLocator == null) + { + return Value.NULL; + } ItemInput itemArg = null; if (lv.size() > inventoryLocator.offset()) { - Value secondArg = lv.get(inventoryLocator.offset()+0); + final Value secondArg = lv.get(inventoryLocator.offset() + 0); if (!secondArg.isNull()) + { itemArg = NBTSerializableValue.parseItem(secondArg.getString(), cc.registryAccess()); + } } int startIndex = 0; - if (lv.size() > inventoryLocator.offset()+1) + if (lv.size() > inventoryLocator.offset() + 1) { - startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong(); + startIndex = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong(); } startIndex = NBTSerializableValue.validateSlot(startIndex, inventoryLocator.inventory()); for (int i = startIndex, maxi = inventoryLocator.inventory().getContainerSize(); i < maxi; i++) { - ItemStack stack = inventoryLocator.inventory().getItem(i); - if ( (itemArg == null && stack.isEmpty()) || (itemArg != null && itemArg.getItem().equals(stack.getItem())) ) + final ItemStack stack = inventoryLocator.inventory().getItem(i); + if ((itemArg == null && stack.isEmpty()) || (itemArg != null && itemArg.getItem().equals(stack.getItem()))) + { return new NumericValue(i); + } } return Value.NULL; }); @@ -327,26 +334,36 @@ public class Inventories { //inventory_remove(, , ) -> bool expression.addContextFunction("inventory_remove", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) return Value.NULL; + final CarpetContext cc = (CarpetContext) c; + final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); + if (inventoryLocator == null) + { + return Value.NULL; + } if (lv.size() <= inventoryLocator.offset()) + { throw new InternalExpressionException("'inventory_remove' requires at least an item to be removed"); - ItemInput searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()).getString(), cc.registryAccess()); + } + final ItemInput searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset()).getString(), cc.registryAccess()); int amount = 1; - if (lv.size() > inventoryLocator.offset()+1) - amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong(); + if (lv.size() > inventoryLocator.offset() + 1) + { + amount = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong(); + } // not enough if (((amount == 1) && (!inventoryLocator.inventory().hasAnyOf(Set.of(searchItem.getItem())))) - || (inventoryLocator.inventory().countItem(searchItem.getItem()) < amount)) return Value.FALSE; + || (inventoryLocator.inventory().countItem(searchItem.getItem()) < amount)) + { + return Value.FALSE; + } for (int i = 0, maxi = inventoryLocator.inventory().getContainerSize(); i < maxi; i++) { - ItemStack stack = inventoryLocator.inventory().getItem(i); - if (stack.isEmpty()) + final ItemStack stack = inventoryLocator.inventory().getItem(i); + if (stack.isEmpty() || !stack.getItem().equals(searchItem.getItem())) + { continue; - if (!stack.getItem().equals(searchItem.getItem())) - continue; - int left = stack.getCount()-amount; + } + final int left = stack.getCount() - amount; if (left > 0) { stack.setCount(left); @@ -354,58 +371,78 @@ public class Inventories { syncPlayerInventory(inventoryLocator, i); return Value.TRUE; } - else - { - inventoryLocator.inventory().removeItemNoUpdate(i); - syncPlayerInventory(inventoryLocator, i); - amount -= stack.getCount(); - } + inventoryLocator.inventory().removeItemNoUpdate(i); + syncPlayerInventory(inventoryLocator, i); + amount -= stack.getCount(); } if (amount > 0) + { throw new InternalExpressionException("Something bad happened - cannot pull all items from inventory"); + } return Value.TRUE; }); //inventory_drop(, , ) -> entity_item (and sets slot) or null if cannot expression.addContextFunction("drop_item", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); - if (inventoryLocator == null) return Value.NULL; - if (lv.size() == inventoryLocator.offset()) - throw new InternalExpressionException("Slot number is required for inventory_drop"); - int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong(); - slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory()); - if (slot == inventoryLocator.inventory().getContainerSize()) return Value.NULL; - int amount = 0; - if (lv.size() > inventoryLocator.offset()+1) - amount = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset()+1)).getLong(); - if (amount < 0) - throw new InternalExpressionException("Cannot throw negative number of items"); - ItemStack stack = inventoryLocator.inventory().getItem(slot); - if (stack == null || stack.isEmpty()) return Value.ZERO; - if (amount == 0) amount = stack.getCount(); - ItemStack droppedStack = inventoryLocator.inventory().removeItem(slot, amount); - if (droppedStack.isEmpty()) return Value.ZERO; - Object owner = inventoryLocator.owner(); - ItemEntity item; - if (owner instanceof Player) + final CarpetContext cc = (CarpetContext) c; + final NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0); + if (inventoryLocator == null) { - item = ((Player) owner).drop(droppedStack, false, true); + return Value.NULL; } - else if (owner instanceof LivingEntity villager) + if (lv.size() == inventoryLocator.offset()) + { + throw new InternalExpressionException("Slot number is required for inventory_drop"); + } + int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset())).getLong(); + slot = NBTSerializableValue.validateSlot(slot, inventoryLocator.inventory()); + if (slot == inventoryLocator.inventory().getContainerSize()) + { + return Value.NULL; + } + int amount = 0; + if (lv.size() > inventoryLocator.offset() + 1) + { + amount = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset() + 1)).getLong(); + } + if (amount < 0) + { + throw new InternalExpressionException("Cannot throw negative number of items"); + } + final ItemStack stack = inventoryLocator.inventory().getItem(slot); + if (stack == null || stack.isEmpty()) + { + return Value.ZERO; + } + if (amount == 0) + { + amount = stack.getCount(); + } + final ItemStack droppedStack = inventoryLocator.inventory().removeItem(slot, amount); + if (droppedStack.isEmpty()) + { + return Value.ZERO; + } + final Object owner = inventoryLocator.owner(); + final ItemEntity item; + if (owner instanceof final Player player) + { + item = player.drop(droppedStack, false, true); + } + else if (owner instanceof LivingEntity livingEntity) { // stolen from LookTargetUtil.give((VillagerEntity)owner, droppedStack, (LivingEntity) owner); - double double_1 = villager.getY() - 0.30000001192092896D + villager.getEyeHeight(); - item = new ItemEntity(villager.level, villager.getX(), double_1, villager.getZ(), droppedStack); - Vec3 vec3d_1 = villager.getViewVector(1.0F).normalize().scale(0.3);// new Vec3d(0, 0.3, 0); - item.setDeltaMovement(vec3d_1); + double double_1 = livingEntity.getY() - 0.30000001192092896D + livingEntity.getEyeHeight(); + item = new ItemEntity(livingEntity.level, livingEntity.getX(), double_1, livingEntity.getZ(), droppedStack); + final Vec3 vec3d = livingEntity.getViewVector(1.0F).normalize().scale(0.3);// new Vec3d(0, 0.3, 0); + item.setDeltaMovement(vec3d); item.setDefaultPickUpDelay(); cc.level().addFreshEntity(item); } else { - Vec3 point = Vec3.atCenterOf(inventoryLocator.position()); //pos+0.5v + final Vec3 point = Vec3.atCenterOf(inventoryLocator.position()); //pos+0.5v item = new ItemEntity(cc.level(), point.x, point.y, point.z, droppedStack); item.setDefaultPickUpDelay(); cc.level().addFreshEntity(item); @@ -413,49 +450,64 @@ public class Inventories { return new NumericValue(item.getItem().getCount()); }); - expression.addContextFunction("create_screen",-1, (c, t, lv) -> + expression.addContextFunction("create_screen", -1, (c, t, lv) -> { - if(lv.size() < 3) throw new InternalExpressionException("'create_screen' requires at least three arguments"); - Value playerValue = lv.get(0); - ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), playerValue); - if(player == null) throw new InternalExpressionException("'create_screen' requires a valid online player as the first argument."); - String type = lv.get(1).getString(); - Component name = FormattedTextValue.getTextByValue(lv.get(2)); + if (lv.size() < 3) + { + throw new InternalExpressionException("'create_screen' requires at least three arguments"); + } + final Value playerValue = lv.get(0); + final ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), playerValue); + if (player == null) + { + throw new InternalExpressionException("'create_screen' requires a valid online player as the first argument."); + } + final String type = lv.get(1).getString(); + final Component name = FormattedTextValue.getTextByValue(lv.get(2)); FunctionValue function = null; - if(lv.size() > 3) + if (lv.size() > 3) + { function = FunctionArgument.findIn(c, expression.module, lv, 3, true, false).function; + } - return new ScreenValue(player,type,name,function,c); + return new ScreenValue(player, type, name, function, c); }); - expression.addContextFunction("close_screen",1, (c, t, lv) -> + expression.addContextFunction("close_screen", 1, (c, t, lv) -> { - Value value = lv.get(0); - if(!(value instanceof ScreenValue screenValue)) throw new InternalExpressionException("'close_screen' requires a screen value as the first argument."); - if(!screenValue.isOpen()) return Value.FALSE; + final Value value = lv.get(0); + if (!(value instanceof final ScreenValue screenValue)) + { + throw new InternalExpressionException("'close_screen' requires a screen value as the first argument."); + } + if (!screenValue.isOpen()) + { + return Value.FALSE; + } screenValue.close(); return Value.TRUE; }); - expression.addContextFunction("screen_property",-1, (c, t, lv) -> + expression.addContextFunction("screen_property", -1, (c, t, lv) -> { - if(lv.size()<2) throw new InternalExpressionException("'screen_property' requires at least a screen and a property name"); - if(!(lv.get(0) instanceof ScreenValue screenValue)) throw new InternalExpressionException("'screen_property' requires a screen value as the first argument"); - String propertyName = lv.get(1).getString(); - if(lv.size()>=3) + if (lv.size() < 2) { - return screenValue.modifyProperty(propertyName,lv.subList(2,lv.size())); + throw new InternalExpressionException("'screen_property' requires at least a screen and a property name"); } - else + if (!(lv.get(0) instanceof final ScreenValue screenValue)) { - return screenValue.queryProperty(propertyName); + throw new InternalExpressionException("'screen_property' requires a screen value as the first argument"); } + final String propertyName = lv.get(1).getString(); + return lv.size() >= 3 + ? screenValue.modifyProperty(propertyName, lv.subList(2, lv.size())) + : screenValue.queryProperty(propertyName); }); } - private static void syncPlayerInventory(NBTSerializableValue.InventoryLocator inventory, int int_1) + private static void syncPlayerInventory(final NBTSerializableValue.InventoryLocator inventory, final int int_1) { - if (inventory.owner() instanceof ServerPlayer player && !inventory.isEnder() && !(inventory.inventory() instanceof ScreenValue.ScreenHandlerInventory)) + if (inventory.owner() instanceof final ServerPlayer player && !inventory.isEnder() && !(inventory.inventory() instanceof ScreenValue.ScreenHandlerInventory)) { player.connection.send(new ClientboundContainerSetSlotPacket( -2, 0, // resolve mystery argument diff --git a/src/main/java/carpet/script/api/Monitoring.java b/src/main/java/carpet/script/api/Monitoring.java index bf8344d8..e32674a2 100644 --- a/src/main/java/carpet/script/api/Monitoring.java +++ b/src/main/java/carpet/script/api/Monitoring.java @@ -1,6 +1,5 @@ package carpet.script.api; -import carpet.fakes.SpawnHelperInnerInterface; import carpet.script.CarpetContext; import carpet.script.Expression; import carpet.script.exception.InternalExpressionException; @@ -24,10 +23,11 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.NaturalSpawner; -public class Monitoring { +public class Monitoring +{ private static final Map MOB_CATEGORY_MAP = Arrays.stream(MobCategory.values()).collect(Collectors.toMap(MobCategory::getName, Function.identity())); - public static void apply(Expression expression) + public static void apply(final Expression expression) { expression.addContextFunction("system_info", -1, (c, t, lv) -> { @@ -35,10 +35,14 @@ public class Monitoring { { return SystemInfo.getAll(); } - if (lv.size() == 1) { - String what = lv.get(0).getString(); - Value res = SystemInfo.get(what, (CarpetContext) c); - if (res == null) throw new InternalExpressionException("Unknown option for 'system_info': " + what); + if (lv.size() == 1) + { + final String what = lv.get(0).getString(); + final Value res = SystemInfo.get(what, (CarpetContext) c); + if (res == null) + { + throw new InternalExpressionException("Unknown option for 'system_info': " + what); + } return res; } throw new InternalExpressionException("'system_info' requires one or no parameters"); @@ -46,18 +50,21 @@ public class Monitoring { // game processed snooper functions expression.addContextFunction("get_mob_counts", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerLevel world = cc.level(); - NaturalSpawner.SpawnState info = world.getChunkSource().getLastSpawnState(); - if (info == null) return Value.NULL; - Object2IntMap mobcounts = info.getMobCategoryCounts(); - int chunks = info.getSpawnableChunkCount(); + final CarpetContext cc = (CarpetContext) c; + final ServerLevel world = cc.level(); + final NaturalSpawner.SpawnState info = world.getChunkSource().getLastSpawnState(); + if (info == null) + { + return Value.NULL; + } + final Object2IntMap mobcounts = info.getMobCategoryCounts(); + final int chunks = info.getSpawnableChunkCount(); if (lv.size() == 0) { - Map retDict = new HashMap<>(); - for (MobCategory category: mobcounts.keySet()) + final Map retDict = new HashMap<>(); + for (final MobCategory category : mobcounts.keySet()) { - int currentCap = (int)(category.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER); + final int currentCap = category.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER; retDict.put( new StringValue(category.getSerializedName().toLowerCase(Locale.ROOT)), ListValue.of( @@ -67,12 +74,15 @@ public class Monitoring { } return MapValue.wrap(retDict); } - String catString = lv.get(0).getString(); - MobCategory cat = MOB_CATEGORY_MAP.get(catString.toLowerCase(Locale.ROOT)); - if (cat == null) throw new InternalExpressionException("Unreconized mob category: "+catString); + final String catString = lv.get(0).getString(); + final MobCategory cat = MOB_CATEGORY_MAP.get(catString.toLowerCase(Locale.ROOT)); + if (cat == null) + { + throw new InternalExpressionException("Unreconized mob category: " + catString); + } return ListValue.of( new NumericValue(mobcounts.getInt(cat)), - new NumericValue((int)(cat.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER)) + new NumericValue((int) (cat.getMaxInstancesPerChunk() * chunks / SpawnReporter.MAGIC_NUMBER)) ); }); } diff --git a/src/main/java/carpet/script/api/Scoreboards.java b/src/main/java/carpet/script/api/Scoreboards.java index dae7769b..f1030d43 100644 --- a/src/main/java/carpet/script/api/Scoreboards.java +++ b/src/main/java/carpet/script/api/Scoreboards.java @@ -16,8 +16,10 @@ import carpet.script.value.StringValue; import carpet.script.value.FormattedTextValue; import carpet.script.value.Value; import com.google.common.collect.Lists; + import java.util.ArrayList; import java.util.List; + import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -35,80 +37,90 @@ import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.scores.Team; import net.minecraft.world.scores.criteria.ObjectiveCriteria; -public class Scoreboards { - private static String getScoreboardKeyFromValue(Value keyValue) +public class Scoreboards +{ + private static String getScoreboardKeyFromValue(final Value keyValue) { - if (keyValue instanceof EntityValue) + if (keyValue instanceof final EntityValue ev) { - Entity e = ((EntityValue) keyValue).getEntity(); - if (e instanceof Player) - { - return e.getName().getString(); - } - else - { - return e.getStringUUID(); - } - } - else - { - return keyValue.getString(); + final Entity e = ev.getEntity(); + return e instanceof Player ? e.getName().getString() : e.getStringUUID(); } + return keyValue.getString(); } - public static void apply(Expression expression) + public static void apply(final Expression expression) { // scoreboard(player,'objective') // scoreboard(player, objective, newValue) expression.addContextFunction("scoreboard", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - Scoreboard scoreboard = cc.server().getScoreboard(); - if (lv.size()==0) - return ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new)); - String objectiveName = lv.get(0).getString(); - Objective objective = scoreboard.getOrCreateObjective(objectiveName); - if (objective == null) return Value.NULL; - if (lv.size()==1) - return ListValue.wrap(scoreboard.getPlayerScores(objective).stream().map(s -> new StringValue(s.getOwner()))); - String key = getScoreboardKeyFromValue(lv.get(1)); - if(lv.size()==2) + final CarpetContext cc = (CarpetContext) c; + final Scoreboard scoreboard = cc.server().getScoreboard(); + if (lv.size() == 0) { - if(!scoreboard.hasPlayerScore(key, objective)) return Value.NULL; - return NumericValue.of(scoreboard.getOrCreatePlayerScore(key,objective).getScore()); + return ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new)); + } + final String objectiveName = lv.get(0).getString(); + final Objective objective = scoreboard.getOrCreateObjective(objectiveName); + if (objective == null) + { + return Value.NULL; + } + if (lv.size() == 1) + { + return ListValue.wrap(scoreboard.getPlayerScores(objective).stream().map(s -> new StringValue(s.getOwner()))); + } + final String key = getScoreboardKeyFromValue(lv.get(1)); + if (lv.size() == 2) + { + return !scoreboard.hasPlayerScore(key, objective) + ? Value.NULL + : NumericValue.of(scoreboard.getOrCreatePlayerScore(key, objective).getScore()); } - Value value = lv.get(2); - if(value.isNull()) { - Score score = scoreboard.getOrCreatePlayerScore(key, objective); - scoreboard.resetPlayerScore(key,objective); + final Value value = lv.get(2); + if (value.isNull()) + { + final Score score = scoreboard.getOrCreatePlayerScore(key, objective); + scoreboard.resetPlayerScore(key, objective); return NumericValue.of(score.getScore()); } - if (value instanceof NumericValue) { - Score score = scoreboard.getOrCreatePlayerScore(key, objective); + if (value instanceof NumericValue) + { + final Score score = scoreboard.getOrCreatePlayerScore(key, objective); score.setScore(NumericValue.asNumber(value).getInt()); return NumericValue.of(score.getScore()); } throw new InternalExpressionException("'scoreboard' requires a number or null as the third parameter"); }); - expression.addContextFunction("scoreboard_remove", -1, (c, t, lv)-> + expression.addContextFunction("scoreboard_remove", -1, (c, t, lv) -> { - if (lv.size()==0) throw new InternalExpressionException("'scoreboard_remove' requires at least one parameter"); - CarpetContext cc = (CarpetContext)c; - Scoreboard scoreboard = cc.server().getScoreboard(); - String objectiveName = lv.get(0).getString(); - Objective objective = scoreboard.getOrCreateObjective(objectiveName); - if (objective == null) return Value.FALSE; + if (lv.size() == 0) + { + throw new InternalExpressionException("'scoreboard_remove' requires at least one parameter"); + } + final CarpetContext cc = (CarpetContext) c; + final Scoreboard scoreboard = cc.server().getScoreboard(); + final String objectiveName = lv.get(0).getString(); + final Objective objective = scoreboard.getOrCreateObjective(objectiveName); + if (objective == null) + { + return Value.FALSE; + } if (lv.size() == 1) { scoreboard.removeObjective(objective); return Value.TRUE; } - String key = getScoreboardKeyFromValue(lv.get(1)); - if (!scoreboard.hasPlayerScore(key, objective)) return Value.NULL; - Score scoreboardPlayerScore = scoreboard.getOrCreatePlayerScore(key, objective); - Value previous = new NumericValue(scoreboardPlayerScore.getScore()); + final String key = getScoreboardKeyFromValue(lv.get(1)); + if (!scoreboard.hasPlayerScore(key, objective)) + { + return Value.NULL; + } + final Score scoreboardPlayerScore = scoreboard.getOrCreatePlayerScore(key, objective); + final Value previous = new NumericValue(scoreboardPlayerScore.getScore()); scoreboard.resetPlayerScore(key, objective); return previous; }); @@ -116,175 +128,247 @@ public class Scoreboards { // objective_add('lvl','level') // objective_add('counter') - expression.addContextFunction("scoreboard_add", -1, (c, t, lv)-> + expression.addContextFunction("scoreboard_add", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - Scoreboard scoreboard = cc.server().getScoreboard(); - if (lv.size() == 0 || lv.size()>2) throw new InternalExpressionException("'scoreboard_add' should have one or two parameters"); - String objectiveName = lv.get(0).getString(); - ObjectiveCriteria criterion; - if (lv.size() == 1 ) + final CarpetContext cc = (CarpetContext) c; + final Scoreboard scoreboard = cc.server().getScoreboard(); + if (lv.size() == 0 || lv.size() > 2) + { + throw new InternalExpressionException("'scoreboard_add' should have one or two parameters"); + } + final String objectiveName = lv.get(0).getString(); + final ObjectiveCriteria criterion; + if (lv.size() == 1) { criterion = ObjectiveCriteria.DUMMY; } else { - String critetionName = lv.get(1).getString(); + final String critetionName = lv.get(1).getString(); criterion = ObjectiveCriteria.byName(critetionName).orElse(null); - if (criterion==null) + if (criterion == null) { throw new ThrowStatement(critetionName, Throwables.UNKNOWN_CRITERION); } } - Objective objective = scoreboard.getOrCreateObjective(objectiveName); - if (objective != null) { + final Objective objective = scoreboard.getOrCreateObjective(objectiveName); + if (objective != null) + { c.host.issueDeprecation("reading or modifying an objective's criterion with scoreboard_add"); - if(lv.size() == 1) return StringValue.of(objective.getCriteria().getName()); - if(objective.getCriteria().equals(criterion) || lv.size() == 1) return Value.NULL; - ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective); + if (lv.size() == 1) + { + return StringValue.of(objective.getCriteria().getName()); + } + if (objective.getCriteria().equals(criterion) || lv.size() == 1) + { + return Value.NULL; + } + ((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective); ((Objective_scarpetMixin) objective).setCriterion(criterion); - (((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); + (((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); scoreboard.onObjectiveAdded(objective); return Value.FALSE; } - scoreboard.addObjective(objectiveName, criterion, Component.literal(objectiveName), criterion.getDefaultRenderType()); return Value.TRUE; }); expression.addContextFunction("scoreboard_property", -1, (c, t, lv) -> { - if(lv.size() < 2) throw new InternalExpressionException("'scoreboard_property' requires at least two parameters"); - CarpetContext cc = (CarpetContext)c; - Scoreboard scoreboard = cc.server().getScoreboard(); - Objective objective = scoreboard.getOrCreateObjective(lv.get(0).getString()); - if(objective == null) return Value.NULL; + if (lv.size() < 2) + { + throw new InternalExpressionException("'scoreboard_property' requires at least two parameters"); + } + final CarpetContext cc = (CarpetContext) c; + final Scoreboard scoreboard = cc.server().getScoreboard(); + final Objective objective = scoreboard.getOrCreateObjective(lv.get(0).getString()); + if (objective == null) + { + return Value.NULL; + } - boolean modify = lv.size() > 2; + final boolean modify = lv.size() > 2; Value setValue = null; - if(modify) { + if (modify) + { setValue = lv.get(2); } - String property = lv.get(1).getString(); - switch (property) { - case "criterion": - if(modify) { - ObjectiveCriteria criterion = ObjectiveCriteria.byName(setValue.getString()).orElse(null); - if (criterion==null) throw new InternalExpressionException("Unknown scoreboard criterion: "+ setValue.getString()); - if(objective.getCriteria().equals(criterion) || lv.size() == 1) return Value.FALSE; - ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective); + final String property = lv.get(1).getString(); + switch (property) + { + case "criterion" -> { + if (modify) + { + final ObjectiveCriteria criterion = ObjectiveCriteria.byName(setValue.getString()).orElse(null); + if (criterion == null) + { + throw new InternalExpressionException("Unknown scoreboard criterion: " + setValue.getString()); + } + if (objective.getCriteria().equals(criterion) || lv.size() == 1) + { + return Value.FALSE; + } + ((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().get(objective.getCriteria()).remove(objective); ((Objective_scarpetMixin) objective).setCriterion(criterion); - (((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); + (((Scoreboard_scarpetMixin) scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); scoreboard.onObjectiveAdded(objective); return Value.TRUE; } return StringValue.of(objective.getCriteria().getName()); - case "display_name": - if(modify) { - Component text = FormattedTextValue.getTextByValue(setValue); + } + case "display_name" -> { + if (modify) + { + final Component text = FormattedTextValue.getTextByValue(setValue); objective.setDisplayName(text); return Value.TRUE; } return new FormattedTextValue(objective.getDisplayName()); - case "display_slot": - if(modify) { - int slotId = Scoreboard.getDisplaySlotByName(setValue.getString()); - if(slotId == -1) throw new InternalExpressionException("Unknown scoreboard display slot: " + setValue.getString()); - if(objective.equals(scoreboard.getDisplayObjective(slotId))) { + } + case "display_slot" -> { + if (modify) + { + final int slotId = Scoreboard.getDisplaySlotByName(setValue.getString()); + if (slotId == -1) + { + throw new InternalExpressionException("Unknown scoreboard display slot: " + setValue.getString()); + } + if (objective.equals(scoreboard.getDisplayObjective(slotId))) + { return Value.FALSE; } - scoreboard.setDisplayObjective(slotId,objective); + scoreboard.setDisplayObjective(slotId, objective); return Value.TRUE; } - - List slots = new ArrayList<>(); - for(int i = 0; i < 19; i++) { - if (scoreboard.getDisplayObjective(i) == objective) { - String slotName = Scoreboard.getDisplaySlotName(i); + final List slots = new ArrayList<>(); + for (int i = 0; i < 19; i++) + { + if (scoreboard.getDisplayObjective(i) == objective) + { + final String slotName = Scoreboard.getDisplaySlotName(i); slots.add(StringValue.of(slotName)); } } return ListValue.wrap(slots); - case "render_type": - if(modify) { - ObjectiveCriteria.RenderType renderType = ObjectiveCriteria.RenderType.byId(setValue.getString().toLowerCase()); - if(objective.getRenderType().equals(renderType)) return Value.FALSE; + } + case "render_type" -> { + if (modify) + { + final ObjectiveCriteria.RenderType renderType = ObjectiveCriteria.RenderType.byId(setValue.getString().toLowerCase()); + if (objective.getRenderType().equals(renderType)) + { + return Value.FALSE; + } objective.setRenderType(renderType); return Value.TRUE; } return StringValue.of(objective.getRenderType().getId()); - default: - throw new InternalExpressionException("scoreboard property '" + property + "' is not a valid property"); + } + default -> throw new InternalExpressionException("scoreboard property '" + property + "' is not a valid property"); } }); expression.addContextFunction("scoreboard_display", 2, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - Scoreboard scoreboard = cc.server().getScoreboard(); - String location = lv.get(0).getString(); - int slot = Scoreboard.getDisplaySlotByName(location); - if (slot < 0) throw new InternalExpressionException("Invalid objective slot: "+location); - Value target = lv.get(1); + final CarpetContext cc = (CarpetContext) c; + final Scoreboard scoreboard = cc.server().getScoreboard(); + final String location = lv.get(0).getString(); + final int slot = Scoreboard.getDisplaySlotByName(location); + if (slot < 0) + { + throw new InternalExpressionException("Invalid objective slot: " + location); + } + final Value target = lv.get(1); if (target.isNull()) { scoreboard.setDisplayObjective(slot, null); return new NumericValue(slot); } - String objectiveString = target.getString(); - Objective objective = scoreboard.getOrCreateObjective(objectiveString); - if (objective == null) return Value.NULL; + final String objectiveString = target.getString(); + final Objective objective = scoreboard.getOrCreateObjective(objectiveString); + if (objective == null) + { + return Value.NULL; + } scoreboard.setDisplayObjective(slot, objective); return new NumericValue(slot); }); expression.addContextFunction("team_list", -1, (c, t, lv) -> { - if(lv.size() > 1) throw new InternalExpressionException("'team_list' requires zero or one parameters"); - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.server().getScoreboard(); - if(lv.size() == 0) + if (lv.size() > 1) + { + throw new InternalExpressionException("'team_list' requires zero or one parameters"); + } + final CarpetContext cc = (CarpetContext) c; + final ServerScoreboard scoreboard = cc.server().getScoreboard(); + if (lv.size() == 0) + { return ListValue.wrap(scoreboard.getTeamNames().stream().map(StringValue::of)); - if (lv.size() != 1) return Value.NULL; - PlayerTeam team = scoreboard.getPlayerTeam(lv.get(0).getString()); - if(team == null) return Value.NULL; - return ListValue.wrap(team.getPlayers().stream().map(StringValue::of)); + } + if (lv.size() != 1) + { + return Value.NULL; + } + final PlayerTeam team = scoreboard.getPlayerTeam(lv.get(0).getString()); + return team == null ? Value.NULL : ListValue.wrap(team.getPlayers().stream().map(StringValue::of)); }); expression.addContextFunction("team_add", -1, (c, t, lv) -> { - if(!(lv.size() < 3 && lv.size() > 0)) throw new InternalExpressionException("'team_add' requires one or two parameters"); - - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.server().getScoreboard(); - String teamName = lv.get(0).getString(); - - if(lv.size() == 1) + if (!(lv.size() < 3 && lv.size() > 0)) { - if (scoreboard.getPlayerTeam(teamName) != null) return Value.NULL; + throw new InternalExpressionException("'team_add' requires one or two parameters"); + } + + final CarpetContext cc = (CarpetContext) c; + final ServerScoreboard scoreboard = cc.server().getScoreboard(); + final String teamName = lv.get(0).getString(); + + if (lv.size() == 1) + { + if (scoreboard.getPlayerTeam(teamName) != null) + { + return Value.NULL; + } scoreboard.addPlayerTeam(teamName); return new StringValue(teamName); } - if(lv.size() != 2) return Value.NULL; - Value playerVal = lv.get(1); - String player = EntityValue.getPlayerNameByValue(playerVal); - if(player == null) return Value.NULL; - PlayerTeam team = scoreboard.getPlayerTeam(teamName); - if(team == null) return Value.NULL; - if(team.isAlliedTo(scoreboard.getPlayersTeam(player))) return Value.FALSE; - scoreboard.addPlayerToTeam(player,scoreboard.getPlayerTeam(teamName)); + if (lv.size() != 2) + { + return Value.NULL; + } + final Value playerVal = lv.get(1); + final String player = EntityValue.getPlayerNameByValue(playerVal); + if (player == null) + { + return Value.NULL; + } + final PlayerTeam team = scoreboard.getPlayerTeam(teamName); + if (team == null) + { + return Value.NULL; + } + if (team.isAlliedTo(scoreboard.getPlayersTeam(player))) + { + return Value.FALSE; + } + scoreboard.addPlayerToTeam(player, scoreboard.getPlayerTeam(teamName)); return Value.TRUE; }); expression.addContextFunction("team_remove", 1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.server().getScoreboard(); - Value teamVal = lv.get(0); - String team = teamVal.getString(); - if(scoreboard.getPlayerTeam(team) == null) return Value.NULL; + final CarpetContext cc = (CarpetContext) c; + final ServerScoreboard scoreboard = cc.server().getScoreboard(); + final Value teamVal = lv.get(0); + final String team = teamVal.getString(); + if (scoreboard.getPlayerTeam(team) == null) + { + return Value.NULL; + } scoreboard.removePlayerTeam(scoreboard.getPlayerTeam(team)); return Value.TRUE; }); @@ -292,212 +376,328 @@ public class Scoreboards { expression.addContextFunction("team_leave", 1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.server().getScoreboard(); - Value playerVal = lv.get(0); - String player = EntityValue.getPlayerNameByValue(playerVal); - if(player == null) return Value.NULL; - return BooleanValue.of(scoreboard.removePlayerFromTeam(player)); + final CarpetContext cc = (CarpetContext) c; + final ServerScoreboard scoreboard = cc.server().getScoreboard(); + final Value playerVal = lv.get(0); + final String player = EntityValue.getPlayerNameByValue(playerVal); + return player == null ? Value.NULL : BooleanValue.of(scoreboard.removePlayerFromTeam(player)); }); expression.addContextFunction("team_property", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerScoreboard scoreboard = cc.server().getScoreboard(); - - if(lv.size() < 2 || lv.size() > 3) throw new InternalExpressionException("'team_property' requires two or three arguments"); - - Value teamVal = lv.get(0); - Value propertyVal = lv.get(1); + final CarpetContext cc = (CarpetContext) c; + final ServerScoreboard scoreboard = cc.server().getScoreboard(); + if (lv.size() < 2 || lv.size() > 3) + { + throw new InternalExpressionException("'team_property' requires two or three arguments"); + } + final Value teamVal = lv.get(0); + final Value propertyVal = lv.get(1); Value settingVal = null; boolean modifying = false; - if(lv.size() == 3) + if (lv.size() == 3) { modifying = true; settingVal = lv.get(2); } - PlayerTeam team = scoreboard.getPlayerTeam(teamVal.getString()); - if(team == null) return Value.NULL; + final PlayerTeam team = scoreboard.getPlayerTeam(teamVal.getString()); + if (team == null) + { + return Value.NULL; + } - if(!(propertyVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the second argument"); + if (!(propertyVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property' requires a string as the second argument"); + } - switch (propertyVal.getString()) { - case "collisionRule": - if(!modifying) return new StringValue(team.getCollisionRule().name); - if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - Team.CollisionRule collisionRule = Team.CollisionRule.byName(settingVal.getString()); - if(collisionRule == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + switch (propertyVal.getString()) + { + case "collisionRule" -> { + if (!modifying) + { + return new StringValue(team.getCollisionRule().name); + } + if (!(settingVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); + } + final Team.CollisionRule collisionRule = Team.CollisionRule.byName(settingVal.getString()); + if (collisionRule == null) + { + throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + } team.setCollisionRule(collisionRule); - break; - case "color": - if(!modifying) return new StringValue(team.getColor().getName()); - if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - ChatFormatting color = ChatFormatting.getByName(settingVal.getString().toUpperCase()); - if(color == null || !color.isColor()) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + } + case "color" -> { + if (!modifying) + { + return new StringValue(team.getColor().getName()); + } + if (!(settingVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); + } + final ChatFormatting color = ChatFormatting.getByName(settingVal.getString().toUpperCase()); + if (color == null || !color.isColor()) + { + throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + } team.setColor(color); - break; - case "deathMessageVisibility": - if(!modifying) return new StringValue(team.getDeathMessageVisibility().name); - if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - Team.Visibility deathMessageVisibility = Team.Visibility.byName(settingVal.getString()); - if(deathMessageVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + } + case "deathMessageVisibility" -> { + if (!modifying) + { + return new StringValue(team.getDeathMessageVisibility().name); + } + if (!(settingVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); + } + final Team.Visibility deathMessageVisibility = Team.Visibility.byName(settingVal.getString()); + if (deathMessageVisibility == null) + { + throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + } team.setDeathMessageVisibility(deathMessageVisibility); - break; - case "displayName": - if(!modifying) return new FormattedTextValue(team.getDisplayName()); - if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Component displayName; - displayName = FormattedTextValue.getTextByValue(settingVal); - team.setDisplayName(displayName); - break; - case "friendlyFire": - if(!modifying) return BooleanValue.of(team.isAllowFriendlyFire()); - if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); - boolean friendlyFire = settingVal.getBoolean(); - team.setAllowFriendlyFire(friendlyFire); - break; - case "nametagVisibility": - if(!modifying) return new StringValue(team.getNameTagVisibility().name); - if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); - Team.Visibility nametagVisibility = Team.Visibility.byName(settingVal.getString()); - if(nametagVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + } + case "displayName" -> { + if (!modifying) + { + return new FormattedTextValue(team.getDisplayName()); + } + if (!(settingVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); + } + team.setDisplayName(FormattedTextValue.getTextByValue(settingVal)); + } + case "friendlyFire" -> { + if (!modifying) + { + return BooleanValue.of(team.isAllowFriendlyFire()); + } + if (!(settingVal instanceof NumericValue)) + { + throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); + } + team.setAllowFriendlyFire(settingVal.getBoolean()); + } + case "nametagVisibility" -> { + if (!modifying) + { + return new StringValue(team.getNameTagVisibility().name); + } + if (!(settingVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString()); + } + final Team.Visibility nametagVisibility = Team.Visibility.byName(settingVal.getString()); + if (nametagVisibility == null) + { + throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString()); + } team.setNameTagVisibility(nametagVisibility); - - break; - case "prefix": - if(!modifying) return new FormattedTextValue(team.getPlayerPrefix()); - if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property ' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Component prefix; - prefix = FormattedTextValue.getTextByValue(settingVal); - team.setPlayerPrefix(prefix); - break; - case "seeFriendlyInvisibles": - if(!modifying) return BooleanValue.of(team.canSeeFriendlyInvisibles()); - if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); - boolean seeFriendlyInvisibles = settingVal.getBoolean(); - team.setSeeFriendlyInvisibles(seeFriendlyInvisibles); - break; - case "suffix": - if(!modifying) return new FormattedTextValue(team.getPlayerSuffix()); - if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); - Component suffix; - suffix = FormattedTextValue.getTextByValue(settingVal); - team.setPlayerSuffix(suffix); - break; - default: - throw new InternalExpressionException("team property '" + propertyVal.getString() + "' is not a valid property"); + } + case "prefix" -> { + if (!modifying) + { + return new FormattedTextValue(team.getPlayerPrefix()); + } + if (!(settingVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property ' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); + } + team.setPlayerPrefix(FormattedTextValue.getTextByValue(settingVal)); + } + case "seeFriendlyInvisibles" -> { + if (!modifying) + { + return BooleanValue.of(team.canSeeFriendlyInvisibles()); + } + if (!(settingVal instanceof NumericValue)) + { + throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString()); + } + team.setSeeFriendlyInvisibles(settingVal.getBoolean()); + } + case "suffix" -> { + if (!modifying) + { + return new FormattedTextValue(team.getPlayerSuffix()); + } + if (!(settingVal instanceof StringValue)) + { + throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString()); + } + team.setPlayerSuffix(FormattedTextValue.getTextByValue(settingVal)); + } + default -> throw new InternalExpressionException("team property '" + propertyVal.getString() + "' is not a valid property"); } return Value.TRUE; }); expression.addContextFunction("bossbar", -1, (c, t, lv) -> { - CustomBossEvents bossBarManager = ((CarpetContext)c).server().getCustomBossEvents(); - if(lv.size() > 3) throw new InternalExpressionException("'bossbar' accepts max three arguments"); - - if(lv.size() == 0) return ListValue.wrap(bossBarManager.getEvents().stream().map(CustomBossEvent::getTextId).map(ResourceLocation::toString).map(StringValue::of)); - - String id = lv.get(0).getString(); - ResourceLocation identifier; - identifier = InputValidator.identifierOf(id); - - if(lv.size() == 1) + final CustomBossEvents bossBarManager = ((CarpetContext) c).server().getCustomBossEvents(); + if (lv.size() > 3) { - if(bossBarManager.get(identifier) != null) return Value.FALSE; - return StringValue.of(bossBarManager.create(identifier,Component.literal(id)).getTextId().toString()); + throw new InternalExpressionException("'bossbar' accepts max three arguments"); } - String property = lv.get(1).getString(); + if (lv.size() == 0) + { + return ListValue.wrap(bossBarManager.getEvents().stream().map(CustomBossEvent::getTextId).map(ResourceLocation::toString).map(StringValue::of)); + } - CustomBossEvent bossBar = bossBarManager.get(identifier); - if(bossBar == null) return Value.NULL; + final String id = lv.get(0).getString(); + final ResourceLocation identifier = InputValidator.identifierOf(id); - Value propertyValue = (lv.size() == 3)?lv.get(2):null; + if (lv.size() == 1) + { + if (bossBarManager.get(identifier) != null) + { + return Value.FALSE; + } + return StringValue.of(bossBarManager.create(identifier, Component.literal(id)).getTextId().toString()); + } - switch (property) { - case "color": - if(propertyValue == null) { - BossEvent.BossBarColor color = (bossBar).getColor(); - if(color == null) return Value.NULL; - return StringValue.of(color.getName()); + final String property = lv.get(1).getString(); + + final CustomBossEvent bossBar = bossBarManager.get(identifier); + if (bossBar == null) + { + return Value.NULL; + } + + final Value propertyValue = (lv.size() == 3) ? lv.get(2) : null; + + switch (property) + { + case "color" -> { + if (propertyValue == null) + { + final BossEvent.BossBarColor color = (bossBar).getColor(); + return color == null ? Value.NULL : StringValue.of(color.getName()); + } + final BossEvent.BossBarColor color = BossEvent.BossBarColor.byName(propertyValue.getString()); + if (color == null) + { + return Value.NULL; } - - BossEvent.BossBarColor color = BossEvent.BossBarColor.byName(propertyValue.getString()); - if(color == null) return Value.NULL; bossBar.setColor(BossEvent.BossBarColor.byName(propertyValue.getString())); return Value.TRUE; - case "max": - if(propertyValue == null) return NumericValue.of(bossBar.getMax()); - - if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); - bossBar.setMax(((NumericValue) propertyValue).getInt()); + } + case "max" -> { + if (propertyValue == null) + { + return NumericValue.of(bossBar.getMax()); + } + if (!(propertyValue instanceof final NumericValue number)) + { + throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); + } + bossBar.setMax(number.getInt()); return Value.TRUE; - case "name": - if(propertyValue == null) return new FormattedTextValue(bossBar.getName()); - + } + case "name" -> { + if (propertyValue == null) + { + return new FormattedTextValue(bossBar.getName()); + } bossBar.setName(FormattedTextValue.getTextByValue(propertyValue)); return Value.TRUE; - case "add_player": - if(propertyValue == null) throw new InternalExpressionException("Bossbar property " + property + " can't be queried, add a third parameter"); - - if(propertyValue instanceof ListValue) { - ((ListValue) propertyValue).getItems().forEach((v)->{ - ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext)c).server(), propertyValue); - if(player != null) bossBar.addPlayer(player); + } + case "add_player" -> { + if (propertyValue == null) + { + throw new InternalExpressionException("Bossbar property " + property + " can't be queried, add a third parameter"); + } + if (propertyValue instanceof final ListValue list) + { + list.getItems().forEach((v) -> { + final ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue); + if (player != null) + { + bossBar.addPlayer(player); + } }); return Value.TRUE; } - - ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue); - if(player != null) { + final ServerPlayer player = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue); + if (player != null) + { bossBar.addPlayer(player); return Value.TRUE; } return Value.FALSE; - case "players": - if (propertyValue == null) return ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new)); - if(propertyValue instanceof ListValue) + } + case "players" -> { + if (propertyValue == null) + { + return ListValue.wrap(bossBar.getPlayers().stream().map(EntityValue::new)); + } + if (propertyValue instanceof final ListValue list) { bossBar.removeAllPlayers(); - ((ListValue) propertyValue).getItems().forEach((v) -> { + list.getItems().forEach(v -> { ServerPlayer p = EntityValue.getPlayerByValue(((CarpetContext) c).server(), v); - if (p != null) bossBar.addPlayer(p); + if (p != null) + { + bossBar.addPlayer(p); + } }); return Value.TRUE; } - - - ServerPlayer p = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue); + final ServerPlayer p = EntityValue.getPlayerByValue(((CarpetContext) c).server(), propertyValue); bossBar.removeAllPlayers(); - if (p != null) { + if (p != null) + { bossBar.addPlayer(p); return Value.TRUE; } return Value.FALSE; - case "style": - if(propertyValue == null) return StringValue.of(bossBar.getOverlay().getName()); - BossEvent.BossBarOverlay style = BossEvent.BossBarOverlay.byName(propertyValue.getString()); - if(style == null) throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property); + } + case "style" -> { + if (propertyValue == null) + { + return StringValue.of(bossBar.getOverlay().getName()); + } + final BossEvent.BossBarOverlay style = BossEvent.BossBarOverlay.byName(propertyValue.getString()); + if (style == null) + { + throw new InternalExpressionException("'" + propertyValue.getString() + "' is not a valid value for property " + property); + } bossBar.setOverlay(style); return Value.TRUE; - case "value": - if(propertyValue == null) return NumericValue.of(bossBar.getValue()); - - if(!(propertyValue instanceof NumericValue)) throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); - bossBar.setValue(((NumericValue) propertyValue).getInt()); + } + case "value" -> { + if (propertyValue == null) + { + return NumericValue.of(bossBar.getValue()); + } + if (!(propertyValue instanceof final NumericValue number)) + { + throw new InternalExpressionException("'bossbar' requires a number as the value for the property " + property); + } + bossBar.setValue(number.getInt()); return Value.TRUE; - case "visible": - if(propertyValue == null) return BooleanValue.of(bossBar.isVisible()); - + } + case "visible" -> { + if (propertyValue == null) + { + return BooleanValue.of(bossBar.isVisible()); + } bossBar.setVisible(propertyValue.getBoolean()); return Value.TRUE; - case "remove": + } + case "remove" -> { bossBarManager.remove(bossBar); return Value.TRUE; - default: - throw new InternalExpressionException("Unknown bossbar property " + property); + } + default -> throw new InternalExpressionException("Unknown bossbar property " + property); } }); } diff --git a/src/main/java/carpet/script/api/Threading.java b/src/main/java/carpet/script/api/Threading.java index 54f55c56..eef25317 100644 --- a/src/main/java/carpet/script/api/Threading.java +++ b/src/main/java/carpet/script/api/Threading.java @@ -16,21 +16,28 @@ public class Threading { //"overidden" native call to cancel if on main thread expression.addContextFunction("task_join", 1, (c, t, lv) -> { - if (((CarpetContext)c).server().isSameThread()) + if (((CarpetContext) c).server().isSameThread()) + { throw new InternalExpressionException("'task_join' cannot be called from main thread to avoid deadlocks"); - Value v = lv.get(0); - if (!(v instanceof ThreadValue)) + } + final Value v = lv.get(0); + if (!(v instanceof final ThreadValue tv)) + { throw new InternalExpressionException("'task_join' could only be used with a task value"); - return ((ThreadValue) v).join(); + } + return tv.join(); }); // has to be lazy due to deferred execution of the expression - expression.addLazyFunctionWithDelegation("task_dock", 1, false,true, (c, t, expr, tok, lv) -> { - CarpetContext cc = (CarpetContext)c; - MinecraftServer server = cc.server(); - if (server.isSameThread()) return lv.get(0); // pass through for on thread tasks - Value[] result = new Value[]{Value.NULL}; - RuntimeException[] internal = new RuntimeException[]{null}; + expression.addLazyFunctionWithDelegation("task_dock", 1, false, true, (c, t, expr, tok, lv) -> { + final CarpetContext cc = (CarpetContext) c; + final MinecraftServer server = cc.server(); + if (server.isSameThread()) + { + return lv.get(0); // pass through for on thread tasks + } + final Value[] result = new Value[]{Value.NULL}; + final RuntimeException[] internal = new RuntimeException[]{null}; try { ((CarpetContext) c).server().executeBlocking(() -> @@ -39,22 +46,22 @@ public class Threading { result[0] = lv.get(0).evalValue(c, t); } - catch (ExpressionException exc) + catch (final ExpressionException exc) { internal[0] = exc; } - catch (InternalExpressionException exc) + catch (final InternalExpressionException exc) { internal[0] = new ExpressionException(c, expr, tok, exc.getMessage(), exc.stack); } - catch (ArithmeticException exc) + catch (final ArithmeticException exc) { - internal[0] = new ExpressionException(c, expr, tok, "Your math is wrong, "+exc.getMessage()); + internal[0] = new ExpressionException(c, expr, tok, "Your math is wrong, " + exc.getMessage()); } }); } - catch (CompletionException exc) + catch (final CompletionException exc) { throw new InternalExpressionException("Error while executing docked task section, internal stack trace is gone"); } @@ -62,7 +69,7 @@ public class Threading { throw internal[0]; } - Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later + final Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later return (_c, _t) -> ret; // pass through placeholder // implmenetation should dock the task on the main thread. diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index 44d3d5e8..5900a3ee 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -137,112 +137,116 @@ import net.minecraft.world.phys.Vec3; import static carpet.script.utils.WorldTools.canHasChunk; -public class WorldAccess { +public class WorldAccess +{ private static final Map DIRECTION_MAP = Arrays.stream(Direction.values()).collect(Collectors.toMap(Direction::getName, (direction) -> direction)); - static { + + static + { DIRECTION_MAP.put("y", Direction.UP); DIRECTION_MAP.put("z", Direction.SOUTH); DIRECTION_MAP.put("x", Direction.EAST); - } + private static final Map> ticketTypes = Map.of( - "portal", TicketType.PORTAL, - "teleport", TicketType.POST_TELEPORT, - "unknown", TicketType.UNKNOWN + "portal", TicketType.PORTAL, + "teleport", TicketType.POST_TELEPORT, + "unknown", TicketType.UNKNOWN ); // dummy entity for dummy requirements in the loot tables (see snowball) private static FallingBlockEntity DUMMY_ENTITY = null; + private static Value booleanStateTest( - Context c, - String name, - List params, - BiPredicate test + final Context c, + final String name, + final List params, + final BiPredicate test ) { - CarpetContext cc = (CarpetContext) c; + final CarpetContext cc = (CarpetContext) c; if (params.size() == 0) + { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); - Value v0 = params.get(0); - if (v0 instanceof BlockValue) - return BooleanValue.of(test.test(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos())); - BlockValue block = BlockArgument.findIn(cc, params, 0).block; + } + if (params.get(0) instanceof final BlockValue bv) + { + return BooleanValue.of(test.test(bv.getBlockState(), bv.getPos())); + } + final BlockValue block = BlockArgument.findIn(cc, params, 0).block; return BooleanValue.of(test.test(block.getBlockState(), block.getPos())); } private static Value stateStringQuery( - Context c, - String name, - List params, - BiFunction test + final Context c, + final String name, + final List params, + final BiFunction test ) { - CarpetContext cc = (CarpetContext) c; + final CarpetContext cc = (CarpetContext) c; if (params.size() == 0) { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); } - - Value v0 = params.get(0); - if (v0 instanceof BlockValue) + if (params.get(0) instanceof final BlockValue bv) { - String strVal = test.apply( ((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos()); - return StringValue.of(strVal); + return StringValue.of(test.apply(bv.getBlockState(), bv.getPos())); } - BlockValue block = BlockArgument.findIn(cc, params, 0).block; + final BlockValue block = BlockArgument.findIn(cc, params, 0).block; return StringValue.of(test.apply(block.getBlockState(), block.getPos())); } private static Value genericStateTest( - Context c, - String name, - List params, - Fluff.TriFunction test + final Context c, + final String name, + final List params, + final Fluff.TriFunction test ) { - CarpetContext cc = (CarpetContext) c; + final CarpetContext cc = (CarpetContext) c; if (params.size() == 0) + { throw new InternalExpressionException("'" + name + "' requires at least one parameter"); - Value v0 = params.get(0); - if (v0 instanceof BlockValue) + } + if (params.get(0) instanceof final BlockValue bv) { try { - return test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos(), cc.level()); + return test.apply(bv.getBlockState(), bv.getPos(), cc.level()); } - catch (NullPointerException ignored) + catch (final NullPointerException ignored) { throw new InternalExpressionException("'" + name + "' function requires a block that is positioned in the world"); } } - BlockValue block = BlockArgument.findIn(cc, params, 0).block; + final BlockValue block = BlockArgument.findIn(cc, params, 0).block; return test.apply(block.getBlockState(), block.getPos(), cc.level()); } - private static > BlockState setProperty(Property property, String name, String value, - BlockState bs) + private static > BlockState setProperty(final Property property, final String name, final String value, + final BlockState bs) { - Optional optional = property.getValue(value); - - if (optional.isPresent()) - { - bs = bs.setValue(property, optional.get()); - } - else + final Optional optional = property.getValue(value); + if (optional.isEmpty()) { throw new InternalExpressionException(value + " is not a valid value for property " + name); } - return bs; + return bs.setValue(property, optional.get()); } - private static void nullCheck(Value v, String name) { - if (v.isNull()) { + private static void nullCheck(final Value v, final String name) + { + if (v.isNull()) + { throw new IllegalArgumentException(name + " cannot be null"); } } - private static float numberGetOrThrow(Value v) { - double num = v.readDoubleNumber(); - if (Double.isNaN(num)) { + private static float numberGetOrThrow(final Value v) + { + final double num = v.readDoubleNumber(); + if (Double.isNaN(num)) + { throw new IllegalArgumentException(v.getString() + " needs to be a numeric value"); } return (float) num; @@ -252,20 +256,20 @@ public class WorldAccess { { synchronized (level) { - ((ChunkGeneratorInterface)level.getChunkSource().getGenerator()).initStrongholds(level); + ((ChunkGeneratorInterface) level.getChunkSource().getGenerator()).initStrongholds(level); } } - public static void apply(Expression expression) + public static void apply(final Expression expression) { expression.addContextFunction("block", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; + final CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) { throw new InternalExpressionException("Block requires at least one parameter"); } - BlockValue retval = BlockArgument.findIn(cc, lv, 0, true).block; + final BlockValue retval = BlockArgument.findIn(cc, lv, 0, true).block; // fixing block state and data retval.getBlockState(); retval.getData(); @@ -275,80 +279,94 @@ public class WorldAccess { expression.addContextFunction("block_data", -1, (c, t, lv) -> { if (lv.size() == 0) + { throw new InternalExpressionException("Block requires at least one parameter"); - CompoundTag tag = BlockArgument.findIn( (CarpetContext) c, lv, 0, true).block.getData(); - return NBTSerializableValue.of(tag); + } + return NBTSerializableValue.of(BlockArgument.findIn((CarpetContext) c, lv, 0, true).block.getData()); }); // poi_get(pos, radius?, type?, occupation?, column_mode?) expression.addContextFunction("poi", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - if (lv.size() == 0) throw new InternalExpressionException("'poi' requires at least one parameter"); - BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); - BlockPos pos = locator.block.getPos(); - PoiManager store = cc.level().getPoiManager(); - Registry poiReg = cc.registry(Registries.POINT_OF_INTEREST_TYPE); + final CarpetContext cc = (CarpetContext) c; + if (lv.size() == 0) + { + throw new InternalExpressionException("'poi' requires at least one parameter"); + } + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); + final BlockPos pos = locator.block.getPos(); + final PoiManager store = cc.level().getPoiManager(); + final Registry poiReg = cc.registry(Registries.POINT_OF_INTEREST_TYPE); if (lv.size() == locator.offset) { - Optional> foo = store.getType(pos); - if (foo.isEmpty()) return Value.NULL; - PoiType poiType = foo.get().value(); + final Optional> foo = store.getType(pos); + if (foo.isEmpty()) + { + return Value.NULL; + } + final PoiType poiType = foo.get().value(); // this feels wrong, but I don't want to mix-in more than I really need to. // also distance adds 0.5 to each point which screws up accurate distance calculations // you shoudn't be using POI with that in mind anyways, so I am not worried about it. - PoiRecord poi = store.getInRange( + final PoiRecord poi = store.getInRange( type -> type.value() == poiType, pos, 1, PoiManager.Occupancy.ANY ).filter(p -> p.getPos().equals(pos)).findFirst().orElse(null); - if (poi == null) - return Value.NULL; - return ListValue.of( + return poi == null ? Value.NULL : ListValue.of( ValueConversions.of(poiReg.getKey(poi.getPoiType().value())), - new NumericValue(poiType.maxTickets() - ((PoiRecord_scarpetMixin)poi).getFreeTickets()) + new NumericValue(poiType.maxTickets() - ((PoiRecord_scarpetMixin) poi).getFreeTickets()) ); } - int radius = NumericValue.asNumber(lv.get(locator.offset+0)).getInt(); - if (radius < 0) return ListValue.of(); + final int radius = NumericValue.asNumber(lv.get(locator.offset + 0)).getInt(); + if (radius < 0) + { + return ListValue.of(); + } Predicate> condition = p -> true; PoiManager.Occupancy status = PoiManager.Occupancy.ANY; boolean inColumn = false; if (locator.offset + 1 < lv.size()) { - String poiType = lv.get(locator.offset+1).getString().toLowerCase(Locale.ROOT); + final String poiType = lv.get(locator.offset + 1).getString().toLowerCase(Locale.ROOT); if (!"any".equals(poiType)) { - PoiType type = poiReg.getOptional(InputValidator.identifierOf(poiType)) + final PoiType type = poiReg.getOptional(InputValidator.identifierOf(poiType)) .orElseThrow(() -> new ThrowStatement(poiType, Throwables.UNKNOWN_POI)); condition = (tt) -> tt.value() == type; } if (locator.offset + 2 < lv.size()) { - String statusString = lv.get(locator.offset+2).getString().toLowerCase(Locale.ROOT); + final String statusString = lv.get(locator.offset + 2).getString().toLowerCase(Locale.ROOT); if ("occupied".equals(statusString)) + { status = PoiManager.Occupancy.IS_OCCUPIED; + } else if ("available".equals(statusString)) + { status = PoiManager.Occupancy.HAS_SPACE; + } else if (!("any".equals(statusString))) + { throw new InternalExpressionException( - "Incorrect POI occupation status "+status+ " use `any`, " + "`occupied` or `available`" + "Incorrect POI occupation status " + status + " use `any`, " + "`occupied` or `available`" ); + } if (locator.offset + 3 < lv.size()) { - inColumn = lv.get(locator.offset+3).getBoolean(); + inColumn = lv.get(locator.offset + 3).getBoolean(); } } } - Stream pois = inColumn? - store.getInSquare(condition, pos, radius, status): + final Stream pois = inColumn ? + store.getInSquare(condition, pos, radius, status) : store.getInRange(condition, pos, radius, status); return ListValue.wrap(pois.sorted(Comparator.comparingDouble(p -> p.getPos().distSqr(pos))).map(p -> ListValue.of( ValueConversions.of(poiReg.getKey(p.getPoiType().value())), - new NumericValue(p.getPoiType().value().maxTickets() - ((PoiRecord_scarpetMixin)p).getFreeTickets()), + new NumericValue(p.getPoiType().value().maxTickets() - ((PoiRecord_scarpetMixin) p).getFreeTickets()), ValueConversions.of(p.getPos()) ) )); @@ -357,98 +375,100 @@ public class WorldAccess { //poi_set(pos, null) poi_set(pos, type, occupied?, expression.addContextFunction("set_poi", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - if (lv.size() == 0) throw new InternalExpressionException("'set_poi' requires at least one parameter"); - BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); - BlockPos pos = locator.block.getPos(); - if (lv.size() < locator.offset) throw new InternalExpressionException("'set_poi' requires the new poi type or null, after position argument"); - Value poi = lv.get(locator.offset+0); - PoiManager store = cc.level().getPoiManager(); + final CarpetContext cc = (CarpetContext) c; + if (lv.size() == 0) + { + throw new InternalExpressionException("'set_poi' requires at least one parameter"); + } + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); + final BlockPos pos = locator.block.getPos(); + if (lv.size() < locator.offset) + { + throw new InternalExpressionException("'set_poi' requires the new poi type or null, after position argument"); + } + final Value poi = lv.get(locator.offset + 0); + final PoiManager store = cc.level().getPoiManager(); if (poi.isNull()) { // clear poi information - if (!store.getType(pos).isPresent()) return Value.FALSE; + if (store.getType(pos).isEmpty()) + { + return Value.FALSE; + } store.remove(pos); return Value.TRUE; } - String poiTypeString = poi.getString().toLowerCase(Locale.ROOT); - ResourceLocation resource = InputValidator.identifierOf(poiTypeString); - Registry poiReg = cc.registry(Registries.POINT_OF_INTEREST_TYPE); - PoiType type = poiReg.getOptional(resource) + final String poiTypeString = poi.getString().toLowerCase(Locale.ROOT); + final ResourceLocation resource = InputValidator.identifierOf(poiTypeString); + final Registry poiReg = cc.registry(Registries.POINT_OF_INTEREST_TYPE); + final PoiType type = poiReg.getOptional(resource) .orElseThrow(() -> new ThrowStatement(poiTypeString, Throwables.UNKNOWN_POI)); - Holder holder = poiReg.getHolderOrThrow(ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, resource)); + final Holder holder = poiReg.getHolderOrThrow(ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, resource)); int occupancy = 0; if (locator.offset + 1 < lv.size()) { - occupancy = (int)NumericValue.asNumber(lv.get(locator.offset + 1)).getLong(); - if (occupancy < 0) throw new InternalExpressionException("Occupancy cannot be negative"); + occupancy = (int) NumericValue.asNumber(lv.get(locator.offset + 1)).getLong(); + if (occupancy < 0) + { + throw new InternalExpressionException("Occupancy cannot be negative"); + } + } + if (store.getType(pos).isPresent()) + { + store.remove(pos); } - if (store.getType(pos).isPresent()) store.remove(pos); store.add(pos, holder); // setting occupancy for a // again - don't want to mix in unnecessarily - peeps not gonna use it that often so not worries about it. if (occupancy > 0) { - int finalO = occupancy; - store.getInSquare((tt) -> tt.value()==type, pos, 1, PoiManager.Occupancy.ANY + final int finalO = occupancy; + store.getInSquare((tt) -> tt.value() == type, pos, 1, PoiManager.Occupancy.ANY ).filter(p -> p.getPos().equals(pos)).findFirst().ifPresent(p -> { - for (int i=0; i < finalO; i++) ((PoiRecord_scarpetMixin)p).callAcquireTicket(); + for (int i = 0; i < finalO; i++) + { + ((PoiRecord_scarpetMixin) p).callAcquireTicket(); + } }); } return Value.TRUE; }); - expression.addContextFunction("weather",-1,(c, t, lv) -> { - ServerLevel world = ((CarpetContext) c).level(); + expression.addContextFunction("weather", -1, (c, t, lv) -> { + final ServerLevel world = ((CarpetContext) c).level(); - if(lv.size()==0)//cos it can thunder when raining or when clear. + if (lv.size() == 0)//cos it can thunder when raining or when clear. + { return new StringValue(world.isThundering() ? "thunder" : (world.isRaining() ? "rain" : "clear")); - - Value weather = lv.get(0); - ServerLevelData worldProperties = ((ServerWorldInterface) world).getWorldPropertiesCM(); - if(lv.size()==1) - { - int ticks; - switch (weather.getString().toLowerCase(Locale.ROOT)) { - case "clear": - ticks = worldProperties.getClearWeatherTime(); - break; - case "rain": - ticks = world.isRaining()? worldProperties.getRainTime():0;//cos if not it gives 1 for some reason - break; - case "thunder": - ticks = world.isThundering()? worldProperties.getThunderTime():0;//same dealio here - break; - default: - throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); - } - return new NumericValue(ticks); } - if(lv.size()==2) + + final Value weather = lv.get(0); + final ServerLevelData worldProperties = ((ServerWorldInterface) world).getWorldPropertiesCM(); + if (lv.size() == 1) { - int ticks = NumericValue.asNumber(lv.get(1), "tick_time in 'weather'").getInt(); + return new NumericValue(switch (weather.getString().toLowerCase(Locale.ROOT)) + { + case "clear" -> worldProperties.getClearWeatherTime(); + case "rain" -> world.isRaining() ? worldProperties.getRainTime() : 0;//cos if not it gives 1 for some reason + case "thunder" -> world.isThundering() ? worldProperties.getThunderTime() : 0;//same dealio here + default -> throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); + }); + } + if (lv.size() == 2) + { + final int ticks = NumericValue.asNumber(lv.get(1), "tick_time in 'weather'").getInt(); switch (weather.getString().toLowerCase(Locale.ROOT)) { - case "clear": - world.setWeatherParameters(ticks,0,false,false); - break; - - case "rain": - world.setWeatherParameters(0,ticks,true,false); - break; - - case "thunder": - world.setWeatherParameters( - 0, - ticks,//this is used to set thunder time, idk why... - true, - true - ); - break; - - default: - throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); + case "clear" -> world.setWeatherParameters(ticks, 0, false, false); + case "rain" -> world.setWeatherParameters(0, ticks, true, false); + case "thunder" -> world.setWeatherParameters( + 0, + ticks,//this is used to set thunder time, idk why... + true, + true + ); + default -> throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'"); } return NumericValue.of(ticks); } @@ -457,41 +477,47 @@ public class WorldAccess { expression.addUnaryFunction("pos", v -> { - if (v instanceof BlockValue) + if (v instanceof final BlockValue bv) { - BlockPos pos = ((BlockValue) v).getPos(); + final BlockPos pos = bv.getPos(); if (pos == null) + { throw new InternalExpressionException("Cannot fetch position of an unrealized block"); + } return ValueConversions.of(pos); } - else if (v instanceof EntityValue) + if (v instanceof final EntityValue ev) { - Entity e = ((EntityValue) v).getEntity(); + final Entity e = ev.getEntity(); if (e == null) + { throw new InternalExpressionException("Null entity"); + } return ValueConversions.of(e.position()); } - else - { - throw new InternalExpressionException("'pos' works only with a block or an entity type"); - } + throw new InternalExpressionException("'pos' works only with a block or an entity type"); }); expression.addContextFunction("pos_offset", -1, (c, t, lv) -> { - BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); - BlockPos pos = locator.block.getPos(); + final BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); + final BlockPos pos = locator.block.getPos(); if (lv.size() <= locator.offset) + { throw new InternalExpressionException("'pos_offset' needs at least position, and direction"); - String directionString = lv.get(locator.offset).getString(); - Direction dir = DIRECTION_MAP.get(directionString); + } + final String directionString = lv.get(locator.offset).getString(); + final Direction dir = DIRECTION_MAP.get(directionString); if (dir == null) - throw new InternalExpressionException("Unknown direction: "+directionString); + { + throw new InternalExpressionException("Unknown direction: " + directionString); + } int howMuch = 1; - if (lv.size() > locator.offset+1) - howMuch = (int) NumericValue.asNumber(lv.get(locator.offset+1)).getLong(); - BlockPos retpos = pos.relative(dir, howMuch); - return ValueConversions.of(retpos); + if (lv.size() > locator.offset + 1) + { + howMuch = (int) NumericValue.asNumber(lv.get(locator.offset + 1)).getLong(); + } + return ValueConversions.of(pos.relative(dir, howMuch)); }); expression.addContextFunction("solid", -1, (c, t, lv) -> @@ -544,33 +570,32 @@ public class WorldAccess { expression.addContextFunction("in_slime_chunk", -1, (c, t, lv) -> { - BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); - ChunkPos chunkPos = new ChunkPos(pos); + final BlockPos pos = BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos(); + final ChunkPos chunkPos = new ChunkPos(pos); return BooleanValue.of(WorldgenRandom.seedSlimeChunk( chunkPos.x, chunkPos.z, - ((CarpetContext)c).level().getSeed(), + ((CarpetContext) c).level().getSeed(), 987234911L ).nextInt(10) == 0); }); expression.addContextFunction("top", -1, (c, t, lv) -> { - String type = lv.get(0).getString().toLowerCase(Locale.ROOT); - Heightmap.Types htype; - switch (type) + final String type = lv.get(0).getString().toLowerCase(Locale.ROOT); + final Heightmap.Types htype = switch (type) { //case "light": htype = Heightmap.Type.LIGHT_BLOCKING; break; //investigate - case "motion": htype = Heightmap.Types.MOTION_BLOCKING; break; - case "terrain": htype = Heightmap.Types.MOTION_BLOCKING_NO_LEAVES; break; - case "ocean_floor": htype = Heightmap.Types.OCEAN_FLOOR; break; - case "surface": htype = Heightmap.Types.WORLD_SURFACE; break; - default: throw new InternalExpressionException("Unknown heightmap type: "+type); - } - BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 1); - BlockPos pos = locator.block.getPos(); - int x = pos.getX(); - int z = pos.getZ(); - return new NumericValue(((CarpetContext)c).level().getChunk(x >> 4, z >> 4).getHeight(htype, x & 15, z & 15) + 1); + case "motion" -> Heightmap.Types.MOTION_BLOCKING; + case "terrain" -> Heightmap.Types.MOTION_BLOCKING_NO_LEAVES; + case "ocean_floor" -> Heightmap.Types.OCEAN_FLOOR; + case "surface" -> Heightmap.Types.WORLD_SURFACE; + default -> throw new InternalExpressionException("Unknown heightmap type: " + type); + }; + final BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 1); + final BlockPos pos = locator.block.getPos(); + final int x = pos.getX(); + final int z = pos.getZ(); + return new NumericValue(((CarpetContext) c).level().getChunk(x >> 4, z >> 4).getHeight(htype, x & 15, z & 15) + 1); }); expression.addContextFunction("loaded", -1, (c, t, lv) -> @@ -580,54 +605,56 @@ public class WorldAccess { expression.addContextFunction("loaded_ep", -1, (c, t, lv) -> { c.host.issueDeprecation("loaded_ep(...)"); - BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); - return BooleanValue.of(((CarpetContext)c).level().isPositionEntityTicking(pos));// 1.17pre1 getChunkManager().shouldTickChunk(new ChunkPos(pos))); + final BlockPos pos = BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos(); + return BooleanValue.of(((CarpetContext) c).level().isPositionEntityTicking(pos)); }); expression.addContextFunction("loaded_status", -1, (c, t, lv) -> { - BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); - LevelChunk chunk = ((CarpetContext)c).level().getChunkSource().getChunk(pos.getX()>>4, pos.getZ()>>4, false); - if (chunk == null) return Value.ZERO; - return new NumericValue(chunk.getFullStatus().ordinal()); + final BlockPos pos = BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos(); + final LevelChunk chunk = ((CarpetContext) c).level().getChunkSource().getChunk(pos.getX() >> 4, pos.getZ() >> 4, false); + return chunk == null ? Value.ZERO : new NumericValue(chunk.getFullStatus().ordinal()); }); expression.addContextFunction("is_chunk_generated", -1, (c, t, lv) -> { - BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); - BlockPos pos = locator.block.getPos(); + final BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); + final BlockPos pos = locator.block.getPos(); boolean force = false; if (lv.size() > locator.offset) + { force = lv.get(locator.offset).getBoolean(); - return BooleanValue.of(canHasChunk(((CarpetContext)c).level(), new ChunkPos(pos), null, force)); + } + return BooleanValue.of(canHasChunk(((CarpetContext) c).level(), new ChunkPos(pos), null, force)); }); expression.addContextFunction("generation_status", -1, (c, t, lv) -> { - BlockArgument blockArgument = BlockArgument.findIn((CarpetContext)c, lv, 0); - BlockPos pos = blockArgument.block.getPos(); + final BlockArgument blockArgument = BlockArgument.findIn((CarpetContext) c, lv, 0); + final BlockPos pos = blockArgument.block.getPos(); boolean forceLoad = false; if (lv.size() > blockArgument.offset) + { forceLoad = lv.get(blockArgument.offset).getBoolean(); - ChunkAccess chunk = ((CarpetContext)c).level().getChunk(pos.getX()>>4, pos.getZ()>>4, ChunkStatus.EMPTY, forceLoad); - if (chunk == null) return Value.NULL; - return new StringValue(chunk.getStatus().getName()); + } + final ChunkAccess chunk = ((CarpetContext) c).level().getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.EMPTY, forceLoad); + return chunk == null ? Value.NULL : new StringValue(chunk.getStatus().getName()); }); expression.addContextFunction("chunk_tickets", -1, (c, t, lv) -> { - ServerLevel world = ((CarpetContext) c).level(); - Long2ObjectOpenHashMap>> levelTickets = ( + final ServerLevel world = ((CarpetContext) c).level(); + final Long2ObjectOpenHashMap>> levelTickets = ( (ChunkTicketManagerInterface) ((ServerChunkManagerInterface) world.getChunkSource()) .getCMTicketManager() ).getTicketsByPosition(); - List res = new ArrayList<>(); + final List res = new ArrayList<>(); if (lv.size() == 0) { - for (long key : levelTickets.keySet()) + for (final long key : levelTickets.keySet()) { - ChunkPos chpos = new ChunkPos(key); - for (Ticket ticket : levelTickets.get(key)) + final ChunkPos chpos = new ChunkPos(key); + for (final Ticket ticket : levelTickets.get(key)) { res.add(ListValue.of( new StringValue(ticket.getType().toString()), @@ -640,12 +667,12 @@ public class WorldAccess { } else { - BlockArgument blockArgument = BlockArgument.findIn((CarpetContext) c, lv, 0); - BlockPos pos = blockArgument.block.getPos(); - SortedArraySet> tickets = levelTickets.get(new ChunkPos(pos).toLong()); + final BlockArgument blockArgument = BlockArgument.findIn((CarpetContext) c, lv, 0); + final BlockPos pos = blockArgument.block.getPos(); + final SortedArraySet> tickets = levelTickets.get(new ChunkPos(pos).toLong()); if (tickets != null) { - for (Ticket ticket : tickets) + for (final Ticket ticket : tickets) { res.add(ListValue.of( new StringValue(ticket.getType().toString()), @@ -677,7 +704,7 @@ public class WorldAccess { expression.addContextFunction("block_tick", -1, (c, t, lv) -> booleanStateTest(c, "block_tick", lv, (s, p) -> { - ServerLevel w = ((CarpetContext)c).level(); + final ServerLevel w = ((CarpetContext) c).level(); s.randomTick(w, p, w.random); return true; })); @@ -685,19 +712,24 @@ public class WorldAccess { expression.addContextFunction("random_tick", -1, (c, t, lv) -> booleanStateTest(c, "random_tick", lv, (s, p) -> { - ServerLevel w = ((CarpetContext)c).level(); + final ServerLevel w = ((CarpetContext) c).level(); if (s.isRandomlyTicking() || s.getFluidState().isRandomlyTicking()) + { s.randomTick(w, p, w.random); + } return true; })); // lazy cause its parked execution expression.addLazyFunction("without_updates", 1, (c, t, lv) -> { - boolean previous = CarpetSettings.impendingFillSkipUpdates.get(); - if (previous) return lv.get(0); - Value [] result = new Value[]{Value.NULL}; - ((CarpetContext)c).server().executeBlocking( () -> + final boolean previous = CarpetSettings.impendingFillSkipUpdates.get(); + if (previous) + { + return lv.get(0); + } + final Value[] result = new Value[]{Value.NULL}; + ((CarpetContext) c).server().executeBlocking(() -> { try { @@ -706,7 +738,7 @@ public class WorldAccess { } finally { - CarpetSettings.impendingFillSkipUpdates.set(previous); + CarpetSettings.impendingFillSkipUpdates.set(false); } }); return (cc, tt) -> result[0]; @@ -714,12 +746,12 @@ public class WorldAccess { expression.addContextFunction("set", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerLevel world = cc.level(); - BlockArgument targetLocator = BlockArgument.findIn(cc, lv, 0); - BlockArgument sourceLocator = BlockArgument.findIn(cc, lv, targetLocator.offset, true); + final CarpetContext cc = (CarpetContext) c; + final ServerLevel world = cc.level(); + final BlockArgument targetLocator = BlockArgument.findIn(cc, lv, 0); + final BlockArgument sourceLocator = BlockArgument.findIn(cc, lv, targetLocator.offset, true); BlockState sourceBlockState = sourceLocator.block.getBlockState(); - BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos()); + final BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos()); CompoundTag data = null; if (lv.size() > sourceLocator.offset) { @@ -728,74 +760,72 @@ public class WorldAccess { { args.add(lv.get(i)); } - if (args.get(0) instanceof ListValue) + if (args.get(0) instanceof final ListValue list) { - if (args.size() == 2) + if (args.size() == 2 && NBTSerializableValue.fromValue(args.get(1)) instanceof final NBTSerializableValue nbtsv) { - Value dataValue = NBTSerializableValue.fromValue( args.get(1)); - if (dataValue instanceof NBTSerializableValue) - { - data = ((NBTSerializableValue) dataValue).getCompoundTag(); - } + data = nbtsv.getCompoundTag(); } - args = ((ListValue) args.get(0)).getItems(); + args = list.getItems(); } - else if (args.get(0) instanceof MapValue) + else if (args.get(0) instanceof final MapValue map) { - if (args.size() == 2) + if (args.size() == 2 && NBTSerializableValue.fromValue(args.get(1)) instanceof final NBTSerializableValue nbtsv) { - Value dataValue = NBTSerializableValue.fromValue( args.get(1)); - if (dataValue instanceof NBTSerializableValue) - { - data = ((NBTSerializableValue) dataValue).getCompoundTag(); - } + data = nbtsv.getCompoundTag(); } - Map state = ((MapValue) args.get(0)).getMap(); - List mapargs = new ArrayList<>(); - state.forEach( (k, v) -> {mapargs.add(k); mapargs.add(v);}); + final Map state = map.getMap(); + final List mapargs = new ArrayList<>(); + state.forEach((k, v) -> { + mapargs.add(k); + mapargs.add(v); + }); args = mapargs; } else { - if ((args.size() & 1) == 1) + if ((args.size() & 1) == 1 && NBTSerializableValue.fromValue(args.get(args.size() - 1)) instanceof final NBTSerializableValue nbtsv) { - Value dataValue = NBTSerializableValue.fromValue( args.get(args.size()-1)); - if (dataValue instanceof NBTSerializableValue) - { - data = ((NBTSerializableValue) dataValue).getCompoundTag(); - } + data = nbtsv.getCompoundTag(); } } - StateDefinition states = sourceBlockState.getBlock().getStateDefinition(); - for (int i = 0; i < args.size()-1; i += 2) + final StateDefinition states = sourceBlockState.getBlock().getStateDefinition(); + for (int i = 0; i < args.size() - 1; i += 2) { - String paramString = args.get(i).getString(); - Property property = states.getProperty(paramString); + final String paramString = args.get(i).getString(); + final Property property = states.getProperty(paramString); if (property == null) + { throw new InternalExpressionException("Property " + paramString + " doesn't apply to " + sourceLocator.block.getString()); - String paramValue = args.get(i + 1).getString(); + } + final String paramValue = args.get(i + 1).getString(); sourceBlockState = setProperty(property, paramString, paramValue, sourceBlockState); } } - if (data == null) data = sourceLocator.block.getData(); - CompoundTag finalData = data; + if (data == null) + { + data = sourceLocator.block.getData(); + } + final CompoundTag finalData = data; if (sourceBlockState == targetBlockState && data == null) + { return Value.FALSE; - BlockState finalSourceBlockState = sourceBlockState; - BlockPos targetPos = targetLocator.block.getPos(); - Boolean[] result = new Boolean[]{true}; - cc.server().executeBlocking( () -> + } + final BlockState finalSourceBlockState = sourceBlockState; + final BlockPos targetPos = targetLocator.block.getPos(); + final Boolean[] result = new Boolean[]{true}; + cc.server().executeBlocking(() -> { Clearable.tryClear(world.getBlockEntity(targetPos)); boolean success = world.setBlock(targetPos, finalSourceBlockState, 2); if (finalData != null) { - BlockEntity be = world.getBlockEntity(targetPos); + final BlockEntity be = world.getBlockEntity(targetPos); if (be != null) { - CompoundTag destTag = finalData.copy(); + final CompoundTag destTag = finalData.copy(); destTag.putInt("x", targetPos.getX()); destTag.putInt("y", targetPos.getY()); destTag.putInt("z", targetPos.getZ()); @@ -806,68 +836,84 @@ public class WorldAccess { } result[0] = success; }); - if (!result[0]) return Value.FALSE; - return new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos()); + return !result[0] ? Value.FALSE : new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos()); }); expression.addContextFunction("destroy", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - ServerLevel world = cc.level(); - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - BlockState state = locator.block.getBlockState(); - if (state.isAir()) return Value.FALSE; - BlockPos where = locator.block.getPos(); - BlockEntity be = world.getBlockEntity(where); + final CarpetContext cc = (CarpetContext) c; + final ServerLevel world = cc.level(); + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final BlockState state = locator.block.getBlockState(); + if (state.isAir()) + { + return Value.FALSE; + } + final BlockPos where = locator.block.getPos(); + final BlockEntity be = world.getBlockEntity(where); long how = 0; Item item = Items.DIAMOND_PICKAXE; boolean playerBreak = false; if (lv.size() > locator.offset) { - Value val = lv.get(locator.offset); - if (val instanceof NumericValue) + final Value val = lv.get(locator.offset); + if (val instanceof final NumericValue number) { - how = ((NumericValue) val).getLong(); + how = number.getLong(); } else { playerBreak = true; - String itemString = val.getString(); + final String itemString = val.getString(); item = cc.registry(Registries.ITEM).getOptional(InputValidator.identifierOf(itemString)) .orElseThrow(() -> new ThrowStatement(itemString, Throwables.UNKNOWN_ITEM)); } } CompoundTag tag = null; - if (lv.size() > locator.offset+1) + if (lv.size() > locator.offset + 1) { - if (!playerBreak) throw new InternalExpressionException("tag is not necessary with 'destroy' with no item"); - Value tagValue = lv.get(locator.offset+1); + if (!playerBreak) + { + throw new InternalExpressionException("tag is not necessary with 'destroy' with no item"); + } + final Value tagValue = lv.get(locator.offset + 1); if (tagValue.isNull()) + { tag = null; - else if (tagValue instanceof NBTSerializableValue) - tag = ((NBTSerializableValue) tagValue).getCompoundTag(); + } + else if (tagValue instanceof final NBTSerializableValue nbtsv) + { + tag = nbtsv.getCompoundTag(); + } else { - NBTSerializableValue readTag = NBTSerializableValue.parseString(tagValue.getString(), true); - tag = readTag.getCompoundTag(); + tag = NBTSerializableValue.parseString(tagValue.getString(), true).getCompoundTag(); } } - ItemStack tool = new ItemStack(item, 1); + final ItemStack tool = new ItemStack(item, 1); if (tag != null) + { tool.setTag(tag); - if (playerBreak && state.getDestroySpeed(world, where) < 0.0) return Value.FALSE; - boolean removed = world.removeBlock(where, false); - if (!removed) return Value.FALSE; + } + if (playerBreak && state.getDestroySpeed(world, where) < 0.0) + { + return Value.FALSE; + } + final boolean removed = world.removeBlock(where, false); + if (!removed) + { + return Value.FALSE; + } world.levelEvent(null, 2001, where, Block.getId(state)); boolean toolBroke = false; boolean dropLoot = true; if (playerBreak) { - boolean isUsingEffectiveTool = !state.requiresCorrectToolForDrops() || tool.isCorrectToolForDrops(state); + final boolean isUsingEffectiveTool = !state.requiresCorrectToolForDrops() || tool.isCorrectToolForDrops(state); //postMine() durability from item classes - float hardness = state.getDestroySpeed(world, where); + final float hardness = state.getDestroySpeed(world, where); int damageAmount = 0; if ((item instanceof DiggerItem && hardness > 0.0) || item instanceof ShearsItem) { @@ -877,9 +923,11 @@ public class WorldAccess { { damageAmount = 2; } - toolBroke = damageAmount>0 && tool.hurt(damageAmount, world.getRandom(), null); + toolBroke = damageAmount > 0 && tool.hurt(damageAmount, world.getRandom(), null); if (!isUsingEffectiveTool) + { dropLoot = false; + } } if (dropLoot) @@ -891,125 +939,163 @@ public class WorldAccess { else { if (how > 0) + { tool.enchant(Enchantments.BLOCK_FORTUNE, (int) how); - if (DUMMY_ENTITY == null) DUMMY_ENTITY = new FallingBlockEntity(EntityType.FALLING_BLOCK, null); + } + if (DUMMY_ENTITY == null) + { + DUMMY_ENTITY = new FallingBlockEntity(EntityType.FALLING_BLOCK, null); + } Block.dropResources(state, world, where, be, DUMMY_ENTITY, tool); } } if (!playerBreak) // no tool info - block brokwn + { return Value.TRUE; + } if (toolBroke) + { return Value.NULL; - Tag outtag = tool.getTag(); - if (outtag == null) - return Value.TRUE; - return new NBTSerializableValue(() -> outtag); + } + final Tag outtag = tool.getTag(); + return outtag == null ? Value.TRUE : new NBTSerializableValue(() -> outtag); }); expression.addContextFunction("harvest", -1, (c, t, lv) -> { - if (lv.size()<2) + if (lv.size() < 2) + { throw new InternalExpressionException("'harvest' takes at least 2 parameters: entity and block, or position, to harvest"); - CarpetContext cc = (CarpetContext)c; - Level world = cc.level(); - Value entityValue = lv.get(0); - if (!(entityValue instanceof EntityValue)) + } + final CarpetContext cc = (CarpetContext) c; + final Level world = cc.level(); + final Value entityValue = lv.get(0); + if (!(entityValue instanceof final EntityValue ev)) + { return Value.FALSE; - Entity e = ((EntityValue) entityValue).getEntity(); - if (!(e instanceof ServerPlayer)) + } + final Entity e = ev.getEntity(); + if (!(e instanceof final ServerPlayer player)) + { return Value.FALSE; - ServerPlayer player = (ServerPlayer)e; - BlockArgument locator = BlockArgument.findIn(cc, lv, 1); - BlockPos where = locator.block.getPos(); - BlockState state = locator.block.getBlockState(); - Block block = state.getBlock(); + } + final BlockArgument locator = BlockArgument.findIn(cc, lv, 1); + final BlockPos where = locator.block.getPos(); + final BlockState state = locator.block.getBlockState(); + final Block block = state.getBlock(); boolean success = false; if (!((block == Blocks.BEDROCK || block == Blocks.BARRIER) && player.gameMode.isSurvival())) + { success = player.gameMode.destroyBlock(where); + } if (success) + { world.levelEvent(null, 2001, where, Block.getId(state)); + } return BooleanValue.of(success); }); expression.addContextFunction("create_explosion", -1, (c, t, lv) -> { if (lv.isEmpty()) + { throw new InternalExpressionException("'create_explosion' requires at least a position to explode"); - CarpetContext cc = (CarpetContext)c; + } + final CarpetContext cc = (CarpetContext) c; float powah = 4.0f; Explosion.BlockInteraction mode = Explosion.BlockInteraction.DESTROY; // should probably read the gamerule for default behaviour boolean createFire = false; Entity source = null; LivingEntity attacker = null; - Vector3Argument location = Vector3Argument.findIn(lv, 0, false, true); - Vec3 pos = location.vec; + final Vector3Argument location = Vector3Argument.findIn(lv, 0, false, true); + final Vec3 pos = location.vec; if (lv.size() > location.offset) { powah = NumericValue.asNumber(lv.get(location.offset), "explosion power").getFloat(); - if (powah < 0) throw new InternalExpressionException("Explosion power cannot be negative"); - if (lv.size() > location.offset+1) + if (powah < 0) { - String strval = lv.get(location.offset+1).getString(); - try { + throw new InternalExpressionException("Explosion power cannot be negative"); + } + if (lv.size() > location.offset + 1) + { + final String strval = lv.get(location.offset + 1).getString(); + try + { mode = Explosion.BlockInteraction.valueOf(strval.toUpperCase(Locale.ROOT)); } - catch (IllegalArgumentException ile) { throw new InternalExpressionException("Illegal explosions block behaviour: "+strval); } - if (lv.size() > location.offset+2) + catch (final IllegalArgumentException ile) { - createFire = lv.get(location.offset+2).getBoolean(); - if (lv.size() > location.offset+3) + throw new InternalExpressionException("Illegal explosions block behaviour: " + strval); + } + if (lv.size() > location.offset + 2) + { + createFire = lv.get(location.offset + 2).getBoolean(); + if (lv.size() > location.offset + 3) { - Value enVal= lv.get(location.offset+3); - if (enVal.isNull()) {} // is null already - else if (enVal instanceof EntityValue) + Value enVal = lv.get(location.offset + 3); + if (enVal.isNull()) { - source = ((EntityValue) enVal).getEntity(); + } // is null already + else if (enVal instanceof final EntityValue ev) + { + source = ev.getEntity(); } else { - throw new InternalExpressionException("Fourth parameter of the explosion has to be an entity, not "+enVal.getTypeString()); + throw new InternalExpressionException("Fourth parameter of the explosion has to be an entity, not " + enVal.getTypeString()); } - if (lv.size() > location.offset+4) + if (lv.size() > location.offset + 4) { - enVal = lv.get(location.offset+4); - if (enVal.isNull()) {} // is null already - else if (enVal instanceof EntityValue) + enVal = lv.get(location.offset + 4); + if (enVal.isNull()) { - Entity attackingEntity = ((EntityValue) enVal).getEntity(); - if (attackingEntity instanceof LivingEntity) + } // is null already + else if (enVal instanceof final EntityValue ev) + { + final Entity attackingEntity = ev.getEntity(); + if (attackingEntity instanceof final LivingEntity le) { - attacker = (LivingEntity) attackingEntity; + attacker = le; + } + else + { + throw new InternalExpressionException("Attacking entity needs to be a living thing, " + + ValueConversions.of(cc.registry(Registries.ENTITY_TYPE).getKey(attackingEntity.getType())).getString() + " ain't it."); } - else throw new InternalExpressionException("Attacking entity needs to be a living thing, "+ - ValueConversions.of(cc.registry(Registries.ENTITY_TYPE).getKey(attackingEntity.getType())).getString() +" ain't it."); - } else { - throw new InternalExpressionException("Fifth parameter of the explosion has to be a living entity, not "+enVal.getTypeString()); + throw new InternalExpressionException("Fifth parameter of the explosion has to be a living entity, not " + enVal.getTypeString()); } } } } } } - LivingEntity theAttacker = attacker; - float thePowah = powah; + final LivingEntity theAttacker = attacker; + final float thePowah = powah; // copy of ServerWorld.createExplosion #TRACK# - Explosion explosion = new Explosion(cc.level(), source, null, null, pos.x, pos.y, pos.z, powah, createFire, mode){ + final Explosion explosion = new Explosion(cc.level(), source, null, null, pos.x, pos.y, pos.z, powah, createFire, mode) + { @Override - public @Nullable LivingEntity getIndirectSourceEntity() { + public @Nullable LivingEntity getIndirectSourceEntity() + { return theAttacker; } }; explosion.explode(); explosion.finalizeExplosion(false); - if (mode == Explosion.BlockInteraction.KEEP) explosion.clearToBlow(); + if (mode == Explosion.BlockInteraction.KEEP) + { + explosion.clearToBlow(); + } cc.level().players().forEach(spe -> { if (spe.distanceToSqr(pos) < 4096.0D) + { spe.connection.send(new ClientboundExplodePacket(pos.x, pos.y, pos.z, thePowah, explosion.getToBlow(), explosion.getHitPlayers().get(spe))); + } }); return Value.TRUE; }); @@ -1017,37 +1103,38 @@ public class WorldAccess { // TODO rename to use_item expression.addContextFunction("place_item", -1, (c, t, lv) -> { - if (lv.size()<2) + if (lv.size() < 2) + { throw new InternalExpressionException("'place_item' takes at least 2 parameters: item and block, or position, to place onto"); - CarpetContext cc = (CarpetContext) c; - String itemString = lv.get(0).getString(); - Vector3Argument locator = Vector3Argument.findIn(lv, 1); - ItemInput stackArg = NBTSerializableValue.parseItem(itemString, cc.registryAccess()); - BlockPos where = new BlockPos(locator.vec); - String facing; - if (lv.size() > locator.offset) { - facing = lv.get(locator.offset).getString(); - } else { - // Paintings throw an exception if their direction is vertical, therefore we change the default here - facing = stackArg.getItem() != Items.PAINTING ? "up" : "north"; } + final CarpetContext cc = (CarpetContext) c; + final String itemString = lv.get(0).getString(); + final Vector3Argument locator = Vector3Argument.findIn(lv, 1); + final ItemInput stackArg = NBTSerializableValue.parseItem(itemString, cc.registryAccess()); + final BlockPos where = new BlockPos(locator.vec); + // Paintings throw an exception if their direction is vertical, therefore we change the default here + final String facing = lv.size() > locator.offset + ? lv.get(locator.offset).getString() + : stackArg.getItem() != Items.PAINTING ? "up" : "north"; boolean sneakPlace = false; - if (lv.size() > locator.offset+1) - sneakPlace = lv.get(locator.offset+1).getBoolean(); + if (lv.size() > locator.offset + 1) + { + sneakPlace = lv.get(locator.offset + 1).getBoolean(); + } - BlockValue.PlacementContext ctx; + final BlockValue.PlacementContext ctx; try { ctx = BlockValue.PlacementContext.from(cc.level(), where, facing, sneakPlace, stackArg.createItemStack(1, false)); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { throw new InternalExpressionException(e.getMessage()); } - if (!(stackArg.getItem() instanceof BlockItem)) + if (!(stackArg.getItem() instanceof final BlockItem blockItem)) { - InteractionResult useResult = ctx.getItemInHand().useOn(ctx); + final InteractionResult useResult = ctx.getItemInHand().useOn(ctx); if (useResult == InteractionResult.CONSUME || useResult == InteractionResult.SUCCESS) { return Value.TRUE; @@ -1055,16 +1142,18 @@ public class WorldAccess { } else { // not sure we need special case for block items, since useOnBlock can do that as well - BlockItem blockItem = (BlockItem) stackArg.getItem(); - if (!ctx.canPlace()) return Value.FALSE; - BlockState placementState = blockItem.getBlock().getStateForPlacement(ctx); + if (!ctx.canPlace()) + { + return Value.FALSE; + } + final BlockState placementState = blockItem.getBlock().getStateForPlacement(ctx); if (placementState != null) { final Level level = ctx.getLevel(); if (placementState.canSurvive(level, where)) { level.setBlock(where, placementState, 2); - SoundType blockSoundGroup = placementState.getSoundType(); + final SoundType blockSoundGroup = placementState.getSoundType(); level.playSound(null, where, blockSoundGroup.getPlaceSound(), SoundSource.BLOCKS, (blockSoundGroup.getVolume() + 1.0F) / 2.0F, blockSoundGroup.getPitch() * 0.8F); return Value.TRUE; } @@ -1087,31 +1176,32 @@ public class WorldAccess { expression.addContextFunction("map_colour", -1, (c, t, lv) -> stateStringQuery(c, "map_colour", lv, (s, p) -> - BlockInfo.mapColourName.get(s.getMapColor(((CarpetContext)c).level(), p)))); + BlockInfo.mapColourName.get(s.getMapColor(((CarpetContext) c).level(), p)))); // Deprecated for block_state() expression.addContextFunction("property", -1, (c, t, lv) -> { c.host.issueDeprecation("property(...)"); - BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); - BlockState state = locator.block.getBlockState(); + final BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); + final BlockState state = locator.block.getBlockState(); if (lv.size() <= locator.offset) + { throw new InternalExpressionException("'property' requires to specify a property to query"); - String tag = lv.get(locator.offset).getString(); - StateDefinition states = state.getBlock().getStateDefinition(); - Property property = states.getProperty(tag); - if (property == null) return Value.NULL; - return new StringValue(state.getValue(property).toString().toLowerCase(Locale.ROOT)); + } + final String tag = lv.get(locator.offset).getString(); + final StateDefinition states = state.getBlock().getStateDefinition(); + final Property property = states.getProperty(tag); + return property == null ? Value.NULL : new StringValue(state.getValue(property).toString().toLowerCase(Locale.ROOT)); }); // Deprecated for block_state() expression.addContextFunction("block_properties", -1, (c, t, lv) -> { c.host.issueDeprecation("block_properties(...)"); - BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); - BlockState state = locator.block.getBlockState(); - StateDefinition states = state.getBlock().getStateDefinition(); + final BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); + final BlockState state = locator.block.getBlockState(); + final StateDefinition states = state.getBlock().getStateDefinition(); return ListValue.wrap(states.getProperties().stream().map( p -> new StringValue(p.getName())) ); @@ -1121,104 +1211,89 @@ public class WorldAccess { // block_state(block, property) expression.addContextFunction("block_state", -1, (c, t, lv) -> { - BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0, true); - BlockState state = locator.block.getBlockState(); - StateDefinition states = state.getBlock().getStateDefinition(); + final BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0, true); + final BlockState state = locator.block.getBlockState(); + final StateDefinition states = state.getBlock().getStateDefinition(); if (locator.offset == lv.size()) { - Map properties = new HashMap<>(); - for(Property p : states.getProperties()) + final Map properties = new HashMap<>(); + for (final Property p : states.getProperties()) { - properties.put(StringValue.of(p.getName()), ValueConversions.fromProperty(state, p));// ValueConversions.fromObject(state.get(p), false)); + properties.put(StringValue.of(p.getName()), ValueConversions.fromProperty(state, p)); } return MapValue.wrap(properties); } - String tag = lv.get(locator.offset).getString(); - Property property = states.getProperty(tag); - if (property == null) - return Value.NULL; - return ValueConversions.fromProperty(state, property); + final String tag = lv.get(locator.offset).getString(); + final Property property = states.getProperty(tag); + return property == null ? Value.NULL : ValueConversions.fromProperty(state, property); }); expression.addContextFunction("block_list", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - Registry blocks = cc.registry(Registries.BLOCK); + final CarpetContext cc = (CarpetContext) c; + final Registry blocks = cc.registry(Registries.BLOCK); if (lv.size() == 0) + { return ListValue.wrap(blocks.keySet().stream().map(ValueConversions::of)); - ResourceLocation tag = InputValidator.identifierOf(lv.get(0).getString()); - - Optional> tagset = blocks.getTag(TagKey.create(Registries.BLOCK, tag)); - if (tagset.isEmpty()) return Value.NULL; - return ListValue.wrap(tagset.get().stream().map(b -> ValueConversions.of(blocks.getKey(b.value())))); + } + final ResourceLocation tag = InputValidator.identifierOf(lv.get(0).getString()); + final Optional> tagset = blocks.getTag(TagKey.create(Registries.BLOCK, tag)); + return tagset.isEmpty() ? Value.NULL : ListValue.wrap(tagset.get().stream().map(b -> ValueConversions.of(blocks.getKey(b.value())))); }); expression.addContextFunction("block_tags", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - Registry blocks = cc.registry(Registries.BLOCK); + final CarpetContext cc = (CarpetContext) c; + final Registry blocks = cc.registry(Registries.BLOCK); if (lv.size() == 0) + { return ListValue.wrap(blocks.getTagNames().map(ValueConversions::of)); - BlockArgument blockLocator = BlockArgument.findIn(cc, lv, 0, true); + } + final BlockArgument blockLocator = BlockArgument.findIn(cc, lv, 0, true); if (blockLocator.offset == lv.size()) { - Block target = blockLocator.block.getBlockState().getBlock(); - return ListValue.wrap( blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == target))).map(e -> ValueConversions.of(e.getFirst()))); + final Block target = blockLocator.block.getBlockState().getBlock(); + return ListValue.wrap(blocks.getTags().filter(e -> e.getSecond().stream().anyMatch(h -> (h.value() == target))).map(e -> ValueConversions.of(e.getFirst()))); } - String tag = lv.get(blockLocator.offset).getString(); - Optional> tagSet = blocks.getTag(TagKey.create(Registries.BLOCK, InputValidator.identifierOf(tag))); - if (tagSet.isEmpty()) return Value.NULL; - return BooleanValue.of(blockLocator.block.getBlockState().is(tagSet.get())); - - - /* before - TagContainer tagManager = cc.s.getServer().getTags(); - if (lv.size() == 0) - return ListValue.wrap(tagManager.getOrEmpty(Registry.BLOCK_REGISTRY).getAvailableTags().stream().map(ValueConversions::of)); - BlockArgument blockLocator = BlockArgument.findIn(cc, lv, 0, true); - if (blockLocator.offset == lv.size()) - { - Block target = blockLocator.block.getBlockState().getBlock(); - return ListValue.wrap(tagManager.getOrEmpty(Registry.BLOCK_REGISTRY).getAllTags().entrySet().stream().filter(e -> e.getValue().contains(target)).map(e -> ValueConversions.of(e.getKey()))); - } - String tag = lv.get(blockLocator.offset).getString(); - net.minecraft.tags.Tag blockTag = tagManager.getOrEmpty(Registry.BLOCK_REGISTRY).getTag(InputValidator.identifierOf(tag)); - if (blockTag == null) return Value.NULL; - return BooleanValue.of(blockLocator.block.getBlockState().is(blockTag)); - */ + final String tag = lv.get(blockLocator.offset).getString(); + final Optional> tagSet = blocks.getTag(TagKey.create(Registries.BLOCK, InputValidator.identifierOf(tag))); + return tagSet.isEmpty() ? Value.NULL : BooleanValue.of(blockLocator.block.getBlockState().is(tagSet.get())); }); expression.addContextFunction("biome", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext) c; - ServerLevel world = cc.level(); + final CarpetContext cc = (CarpetContext) c; + final ServerLevel world = cc.level(); if (lv.size() == 0) + { return ListValue.wrap(world.registryAccess().registryOrThrow(Registries.BIOME).keySet().stream().map(ValueConversions::of)); + } - Biome biome; - BiomeSource biomeSource = world.getChunkSource().getGenerator().getBiomeSource(); - if ( lv.size() == 1 - && lv.get(0) instanceof MapValue map - && biomeSource instanceof MultiNoiseBiomeSource mnbs - ) { - Value temperature = map.get(new StringValue("temperature")); + final Biome biome; + final BiomeSource biomeSource = world.getChunkSource().getGenerator().getBiomeSource(); + if (lv.size() == 1 + && lv.get(0) instanceof final MapValue map + && biomeSource instanceof final MultiNoiseBiomeSource mnbs + ) + { + final Value temperature = map.get(new StringValue("temperature")); nullCheck(temperature, "temperature"); - Value humidity = map.get(new StringValue("humidity")); + final Value humidity = map.get(new StringValue("humidity")); nullCheck(humidity, "humidity"); - Value continentalness = map.get(new StringValue("continentalness")); + final Value continentalness = map.get(new StringValue("continentalness")); nullCheck(continentalness, "continentalness"); - Value erosion = map.get(new StringValue("erosion")); + final Value erosion = map.get(new StringValue("erosion")); nullCheck(erosion, "erosion"); - Value depth = map.get(new StringValue("depth")); + final Value depth = map.get(new StringValue("depth")); nullCheck(depth, "depth"); - Value weirdness = map.get(new StringValue("weirdness")); + final Value weirdness = map.get(new StringValue("weirdness")); nullCheck(weirdness, "weirdness"); - Climate.TargetPoint point = new Climate.TargetPoint( + final Climate.TargetPoint point = new Climate.TargetPoint( Climate.quantizeCoord(numberGetOrThrow(temperature)), Climate.quantizeCoord(numberGetOrThrow(humidity)), Climate.quantizeCoord(numberGetOrThrow(continentalness)), @@ -1227,127 +1302,145 @@ public class WorldAccess { Climate.quantizeCoord(numberGetOrThrow(weirdness)) ); biome = mnbs.getNoiseBiome(point).value(); - ResourceLocation biomeId = cc.registry(Registries.BIOME).getKey(biome); + final ResourceLocation biomeId = cc.registry(Registries.BIOME).getKey(biome); return new StringValue(NBTSerializableValue.nameFromRegistryId(biomeId)); } - BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false, false, true); + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false, false, true); if (locator.replacement != null) { biome = world.registryAccess().registryOrThrow(Registries.BIOME).get(InputValidator.identifierOf(locator.replacement)); - if (biome == null) throw new ThrowStatement(locator.replacement, Throwables.UNKNOWN_BIOME); + if (biome == null) + { + throw new ThrowStatement(locator.replacement, Throwables.UNKNOWN_BIOME); + } } else { - BlockPos pos = locator.block.getPos(); - biome = world.getBiome(pos).value(); + biome = world.getBiome(locator.block.getPos()).value(); } // in locatebiome if (locator.offset == lv.size()) { - ResourceLocation biomeId = cc.registry(Registries.BIOME).getKey(biome); + final ResourceLocation biomeId = cc.registry(Registries.BIOME).getKey(biome); return new StringValue(NBTSerializableValue.nameFromRegistryId(biomeId)); } - String biomeFeature = lv.get(locator.offset).getString(); - BiFunction featureProvider = BiomeInfo.biomeFeatures.get(biomeFeature); + final String biomeFeature = lv.get(locator.offset).getString(); + final BiFunction featureProvider = BiomeInfo.biomeFeatures.get(biomeFeature); if (featureProvider == null) + { throw new InternalExpressionException("Unknown biome feature: " + biomeFeature); + } return featureProvider.apply(world, biome); }); expression.addContextFunction("set_biome", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(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).getString(); - // from locatebiome command code - Holder biome = cc.registry(Registries.BIOME).getHolder(ResourceKey.create(Registries.BIOME, InputValidator.identifierOf(biomeName))) - .orElseThrow(() -> new ThrowStatement(biomeName, Throwables.UNKNOWN_BIOME)); - - - boolean doImmediateUpdate = true; - if (lv.size() > locator.offset+1) { - doImmediateUpdate = lv.get(locator.offset+1).getBoolean(); + throw new InternalExpressionException("'set_biome' needs a biome name as an argument"); } - ServerLevel world = cc.level(); - BlockPos pos = locator.block.getPos(); - ChunkAccess chunk = world.getChunk(pos); // getting level chunk instead of protochunk with biomes - int biomeX = QuartPos.fromBlock(pos.getX()); - int biomeY = QuartPos.fromBlock(pos.getY()); - int biomeZ = QuartPos.fromBlock(pos.getZ()); - try { - int i = QuartPos.fromBlock(chunk.getMinBuildHeight()); - int j = i + QuartPos.fromBlock(chunk.getHeight()) - 1; - int k = Mth.clamp(biomeY, i, j); - int l = chunk.getSectionIndex(QuartPos.toBlock(k)); + final String biomeName = lv.get(locator.offset + 0).getString(); + // from locatebiome command code + final Holder biome = cc.registry(Registries.BIOME).getHolder(ResourceKey.create(Registries.BIOME, InputValidator.identifierOf(biomeName))) + .orElseThrow(() -> new ThrowStatement(biomeName, Throwables.UNKNOWN_BIOME)); + boolean doImmediateUpdate = true; + if (lv.size() > locator.offset + 1) + { + doImmediateUpdate = lv.get(locator.offset + 1).getBoolean(); + } + final ServerLevel world = cc.level(); + final BlockPos pos = locator.block.getPos(); + final ChunkAccess chunk = world.getChunk(pos); // getting level chunk instead of protochunk with biomes + final int biomeX = QuartPos.fromBlock(pos.getX()); + final int biomeY = QuartPos.fromBlock(pos.getY()); + final int biomeZ = QuartPos.fromBlock(pos.getZ()); + try + { + final int i = QuartPos.fromBlock(chunk.getMinBuildHeight()); + final int j = i + QuartPos.fromBlock(chunk.getHeight()) - 1; + final int k = Mth.clamp(biomeY, i, j); + final int l = chunk.getSectionIndex(QuartPos.toBlock(k)); // accessing outside of the interface - might be dangerous in the future. ((PalettedContainer>) chunk.getSection(l).getBiomes()).set(biomeX & 3, k & 3, biomeZ & 3, biome); - } catch (Throwable var8) { + } + catch (final Throwable var8) + { return Value.FALSE; } - if (doImmediateUpdate) WorldTools.forceChunkUpdate(pos, world); + if (doImmediateUpdate) + { + WorldTools.forceChunkUpdate(pos, world); + } chunk.setUnsaved(true); return Value.TRUE; }); expression.addContextFunction("reload_chunk", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockPos pos = BlockArgument.findIn(cc, lv, 0).block.getPos(); - ServerLevel world = cc.level(); - cc.server().executeBlocking( () -> WorldTools.forceChunkUpdate(pos, world)); + final CarpetContext cc = (CarpetContext) c; + final BlockPos pos = BlockArgument.findIn(cc, lv, 0).block.getPos(); + final ServerLevel world = cc.level(); + cc.server().executeBlocking(() -> WorldTools.forceChunkUpdate(pos, world)); return Value.TRUE; }); expression.addContextFunction("structure_references", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - ServerLevel world = cc.level(); - BlockPos pos = locator.block.getPos(); - Map references = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences(); - Registry reg = cc.registry(Registries.STRUCTURE); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final ServerLevel world = cc.level(); + final BlockPos pos = locator.block.getPos(); + final Map references = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_REFERENCES).getAllReferences(); + final Registry reg = cc.registry(Registries.STRUCTURE); if (lv.size() == locator.offset) + { return ListValue.wrap(references.entrySet().stream(). - filter(e -> e.getValue()!= null && !e.getValue().isEmpty()). + filter(e -> e.getValue() != null && !e.getValue().isEmpty()). map(e -> new StringValue(NBTSerializableValue.nameFromRegistryId(reg.getKey(e.getKey())))) ); - String simpleStructureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); - Structure structureName = reg.get(InputValidator.identifierOf(simpleStructureName)); - if (structureName == null) return Value.NULL; - LongSet structureReferences = references.get(structureName); - if (structureReferences == null || structureReferences.isEmpty()) return ListValue.of(); + } + final String simpleStructureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); + final Structure structureName = reg.get(InputValidator.identifierOf(simpleStructureName)); + if (structureName == null) + { + return Value.NULL; + } + final LongSet structureReferences = references.get(structureName); + if (structureReferences == null || structureReferences.isEmpty()) + { + return ListValue.of(); + } return ListValue.wrap(structureReferences.longStream().mapToObj(l -> ListValue.of( - new NumericValue(16*ChunkPos.getX(l)), + new NumericValue(16 * ChunkPos.getX(l)), Value.ZERO, - new NumericValue(16*ChunkPos.getZ(l))))); + new NumericValue(16 * ChunkPos.getZ(l))))); }); expression.addContextFunction("structure_eligibility", -1, (c, t, lv) -> {// TODO rename structureName to class - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - ServerLevel world = cc.level(); + final ServerLevel world = cc.level(); // well, because BooYah(world); - BlockPos pos = locator.block.getPos(); + final BlockPos pos = locator.block.getPos(); final List structure = new ArrayList<>(); boolean needSize = false; boolean singleOutput = false; - Registry reg = cc.registry(Registries.STRUCTURE); + final Registry reg = cc.registry(Registries.STRUCTURE); if (lv.size() > locator.offset) { - Value requested = lv.get(locator.offset+0); + final Value requested = lv.get(locator.offset + 0); if (!requested.isNull()) { - String reqString = requested.getString(); - var id = InputValidator.identifierOf(reqString); - Structure requestedStructure = reg.get(id); + final String reqString = requested.getString(); + final ResourceLocation id = InputValidator.identifierOf(reqString); + final Structure requestedStructure = reg.get(id); if (requestedStructure != null) { singleOutput = true; @@ -1355,8 +1448,8 @@ public class WorldAccess { } else { - StructureType sss = cc.registry(Registries.STRUCTURE_TYPE).get(id); - reg.entrySet().stream().filter(e -> e.getValue().type() ==sss).forEach(e -> structure.add(e.getValue())); + final StructureType sss = cc.registry(Registries.STRUCTURE_TYPE).get(id); + reg.entrySet().stream().filter(e -> e.getValue().type() == sss).forEach(e -> structure.add(e.getValue())); } if (structure.isEmpty()) { @@ -1368,9 +1461,9 @@ public class WorldAccess { { structure.addAll(reg.entrySet().stream().map(Map.Entry::getValue).toList()); } - if (lv.size() > locator.offset+1) + if (lv.size() > locator.offset + 1) { - needSize = lv.get(locator.offset+1).getBoolean(); + needSize = lv.get(locator.offset + 1).getBoolean(); } } else @@ -1379,50 +1472,53 @@ public class WorldAccess { } if (singleOutput) { - StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, structure.get(0), needSize); - if (start == null) return Value.NULL; - if (!needSize) return Value.TRUE; - return ValueConversions.of(start, cc.registryAccess()); + final StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, structure.get(0), needSize); + return start == null ? Value.NULL : !needSize ? Value.TRUE : ValueConversions.of(start, cc.registryAccess()); } - Map ret = new HashMap<>(); - for(Structure str: structure) + final Map ret = new HashMap<>(); + for (final Structure str : structure) { StructureStart start; try { start = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize); } - catch (NullPointerException npe) + catch (final NullPointerException npe) { - CarpetSettings.LOG.error("Failed to detect structure: "+ reg.getKey(str)); + CarpetSettings.LOG.error("Failed to detect structure: " + reg.getKey(str)); start = null; } - if (start == null) continue; + if (start == null) + { + continue; + } - Value key = new StringValue(NBTSerializableValue.nameFromRegistryId(reg.getKey(str))); - ret.put(key, (!needSize)?Value.NULL: ValueConversions.of(start, cc.registryAccess())); + final Value key = new StringValue(NBTSerializableValue.nameFromRegistryId(reg.getKey(str))); + ret.put(key, (!needSize) ? Value.NULL : ValueConversions.of(start, cc.registryAccess())); } return MapValue.wrap(ret); }); expression.addContextFunction("structures", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - ServerLevel world = cc.level(); - BlockPos pos = locator.block.getPos(); - Map structures = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_STARTS).getAllStarts(); - Registry reg = cc.registry(Registries.STRUCTURE); + final ServerLevel world = cc.level(); + final BlockPos pos = locator.block.getPos(); + final Map structures = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_STARTS).getAllStarts(); + final Registry reg = cc.registry(Registries.STRUCTURE); if (lv.size() == locator.offset) { - Map structureList = new HashMap<>(); - for (Map.Entry entry : structures.entrySet()) + final Map structureList = new HashMap<>(); + for (final Map.Entry entry : structures.entrySet()) { - StructureStart start = entry.getValue(); + final StructureStart start = entry.getValue(); if (start == StructureStart.INVALID_START) + { continue; - BoundingBox box = start.getBoundingBox(); + } + final BoundingBox box = start.getBoundingBox(); structureList.put( new StringValue(NBTSerializableValue.nameFromRegistryId(reg.getKey(entry.getKey()))), ValueConversions.of(box) @@ -1430,57 +1526,67 @@ public class WorldAccess { } return MapValue.wrap(structureList); } - String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); + final String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); return ValueConversions.of(structures.get(reg.get(InputValidator.identifierOf(structureName))), cc.registryAccess()); }); expression.addContextFunction("set_structure", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - ServerLevel world = cc.level(); - BlockPos pos = locator.block.getPos(); + final ServerLevel world = cc.level(); + final BlockPos pos = locator.block.getPos(); if (lv.size() == locator.offset) + { throw new InternalExpressionException("'set_structure requires at least position and a structure name"); - String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); - Structure configuredStructure = FeatureGenerator.resolveConfiguredStructure(structureName, world, pos); - if (configuredStructure == null) throw new ThrowStatement(structureName, Throwables.UNKNOWN_STRUCTURE); + } + final String structureName = lv.get(locator.offset).getString().toLowerCase(Locale.ROOT); + final Structure configuredStructure = FeatureGenerator.resolveConfiguredStructure(structureName, world, pos); + if (configuredStructure == null) + { + throw new ThrowStatement(structureName, Throwables.UNKNOWN_STRUCTURE); + } // good 'ol pointer - Value[] result = new Value[]{Value.NULL}; + final Value[] result = new Value[]{Value.NULL}; // technically a world modification. Even if we could let it slide, we will still park it ((CarpetContext) c).server().executeBlocking(() -> { - Map structures = world.getChunk(pos).getAllStarts(); + final Map structures = world.getChunk(pos).getAllStarts(); if (lv.size() == locator.offset + 1) { - Boolean res = FeatureGenerator.plopGrid(configuredStructure, ((CarpetContext) c).level(), locator.block.getPos()); - if (res == null) return; - result[0] = res?Value.TRUE:Value.FALSE; + final Boolean res = FeatureGenerator.plopGrid(configuredStructure, ((CarpetContext) c).level(), locator.block.getPos()); + if (res == null) + { + return; + } + result[0] = res ? Value.TRUE : Value.FALSE; return; } - Value newValue = lv.get(locator.offset+1); + final Value newValue = lv.get(locator.offset + 1); if (newValue.isNull()) // remove structure { - Structure structure = configuredStructure; + final Structure structure = configuredStructure; if (!structures.containsKey(structure)) { return; } - StructureStart start = structures.get(structure); - ChunkPos structureChunkPos = start.getChunkPos(); - BoundingBox box = start.getBoundingBox(); + final StructureStart start = structures.get(structure); + final ChunkPos structureChunkPos = start.getChunkPos(); + final BoundingBox box = start.getBoundingBox(); for (int chx = box.minX() / 16; chx <= box.maxX() / 16; chx++) // minx maxx { for (int chz = box.minZ() / 16; chz <= box.maxZ() / 16; chz++) //minZ maxZ { - ChunkPos chpos = new ChunkPos(chx, chz); + final ChunkPos chpos = new ChunkPos(chx, chz); // getting a chunk will convert it to full, allowing to modify references - Map references = + final Map references = world.getChunk(chpos.getWorldPosition()).getAllReferences(); if (references.containsKey(structure) && references.get(structure) != null) + { references.get(structure).remove(structureChunkPos.toLong()); + } } } structures.remove(structure); @@ -1489,46 +1595,19 @@ public class WorldAccess { }); return result[0]; // preventing from lazy evaluating of the result in case a future completes later }); -/* - expression.addContextFunction("custom_dimension", -1, (c, t, lv) -> - { - if (lv.size() == 0) throw new InternalExpressionException("'custom_dimension' requires at least one argument"); - CarpetContext cc = (CarpetContext)c; - cc.host.issueDeprecation("custom_dimension()"); - String worldKey = lv.get(0).getString(); - Long seed = null; - if (lv.size() > 1) - { - String seedKey = lv.get(1).getString(); - try - { - seed = Long.parseLong(seedKey); - } - catch (NumberFormatException ignored) - { - throw new InternalExpressionException("Incorrect number format for seed: " + seedKey); - } - } - - boolean success = WorldTools.createWorld(cc.s.getServer(), worldKey, seed); - if (!success) return Value.FALSE; - CommandHelper.notifyPlayersCommandsChanged(cc.s.getServer()); - return Value.TRUE; - }); -*/ // todo maybe enable chunk blending? expression.addContextFunction("reset_chunk", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - List requestedChunks = new ArrayList<>(); + final CarpetContext cc = (CarpetContext) c; + final List requestedChunks = new ArrayList<>(); if (lv.size() == 1) { //either one block or list of chunks - Value first = lv.get(0); - if (first instanceof ListValue) + final Value first = lv.get(0); + if (first instanceof final ListValue list) { - List listVal = ((ListValue) first).getItems(); + final List listVal = list.getItems(); BlockArgument locator = BlockArgument.findIn(cc, listVal, 0); requestedChunks.add(new ChunkPos(locator.block.getPos())); while (listVal.size() > locator.offset) @@ -1539,23 +1618,26 @@ public class WorldAccess { } else { - BlockArgument locator = BlockArgument.findIn(cc, Collections.singletonList(first), 0); + final BlockArgument locator = BlockArgument.findIn(cc, Collections.singletonList(first), 0); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } else { BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - ChunkPos from = new ChunkPos(locator.block.getPos()); + final ChunkPos from = new ChunkPos(locator.block.getPos()); if (lv.size() > locator.offset) { locator = BlockArgument.findIn(cc, lv, locator.offset); - ChunkPos to = new ChunkPos(locator.block.getPos()); - int xmax = Math.max(from.x, to.x); - int zmax = Math.max(from.z, to.z); - for (int x = Math.min(from.x, to.x); x <= xmax; x++) for (int z = Math.min(from.z, to.z); z <= zmax; z++) + final ChunkPos to = new ChunkPos(locator.block.getPos()); + final int xmax = Math.max(from.x, to.x); + final int zmax = Math.max(from.z, to.z); + for (int x = Math.min(from.x, to.x); x <= xmax; x++) { - requestedChunks.add(new ChunkPos(x,z)); + for (int z = Math.min(from.z, to.z); z <= zmax; z++) + { + requestedChunks.add(new ChunkPos(x, z)); + } } } else @@ -1563,25 +1645,14 @@ public class WorldAccess { requestedChunks.add(from); } } - - - ServerLevel world = cc.level(); - - Value [] result = new Value[]{Value.NULL}; - - ((CarpetContext)c).server().executeBlocking( () -> + final ServerLevel world = cc.level(); + final Value[] result = new Value[]{Value.NULL}; + ((CarpetContext) c).server().executeBlocking(() -> { - Map report = ((ThreadedAnvilChunkStorageInterface) world.getChunkSource().chunkMap).regenerateChunkRegion(requestedChunks); - /*for (ChunkPos chpos: requestedChunks) // needed in 1.16 only - { - if (world.getChunk(chpos.x, chpos.z, ChunkStatus.FULL, false) != null) - { - WorldTools.forceChunkUpdate(chpos.getStartPos(), world); - } - }*/ + final Map report = ((ThreadedAnvilChunkStorageInterface) world.getChunkSource().chunkMap).regenerateChunkRegion(requestedChunks); result[0] = MapValue.wrap(report.entrySet().stream().collect(Collectors.toMap( e -> new StringValue(e.getKey()), - e -> new NumericValue(e.getValue()) + e -> new NumericValue(e.getValue()) ))); }); return result[0]; @@ -1589,73 +1660,92 @@ public class WorldAccess { expression.addContextFunction("inhabited_time", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - BlockPos pos = locator.block.getPos(); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final BlockPos pos = locator.block.getPos(); return new NumericValue(cc.level().getChunk(pos).getInhabitedTime()); }); expression.addContextFunction("spawn_potential", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - BlockPos pos = locator.block.getPos(); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final BlockPos pos = locator.block.getPos(); double required_charge = 1; if (lv.size() > locator.offset) + { required_charge = NumericValue.asNumber(lv.get(locator.offset)).getDouble(); - NaturalSpawner.SpawnState charger = cc.level().getChunkSource().getLastSpawnState(); - if (charger == null) return Value.NULL; - return new NumericValue( - ((SpawnHelperInnerInterface)charger).getPotentialCalculator(). - getPotentialEnergyChange(pos, required_charge ) + } + final NaturalSpawner.SpawnState charger = cc.level().getChunkSource().getLastSpawnState(); + return charger == null ? Value.NULL : new NumericValue( + ((SpawnHelperInnerInterface) charger).getPotentialCalculator(). + getPotentialEnergyChange(pos, required_charge) ); }); expression.addContextFunction("add_chunk_ticket", -1, (c, t, lv) -> { - CarpetContext cc = (CarpetContext)c; - BlockArgument locator = BlockArgument.findIn(cc, lv, 0); - BlockPos pos = locator.block.getPos(); - if (lv.size() != locator.offset+2) throw new InternalExpressionException("'add_chunk_ticket' requires block position, ticket type and radius"); - String type = lv.get(locator.offset).getString(); - TicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); - if (ticket == null) throw new InternalExpressionException("Unknown ticket type: "+type); - int radius = NumericValue.asNumber(lv.get(locator.offset+1)).getInt(); - if (radius < 1 || radius > 32) throw new InternalExpressionException("Ticket radius should be between 1 and 32 chunks"); + final CarpetContext cc = (CarpetContext) c; + final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + final BlockPos pos = locator.block.getPos(); + if (lv.size() != locator.offset + 2) + { + throw new InternalExpressionException("'add_chunk_ticket' requires block position, ticket type and radius"); + } + final String type = lv.get(locator.offset).getString(); + final TicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); + if (ticket == null) + { + throw new InternalExpressionException("Unknown ticket type: " + type); + } + final int radius = NumericValue.asNumber(lv.get(locator.offset + 1)).getInt(); + if (radius < 1 || radius > 32) + { + throw new InternalExpressionException("Ticket radius should be between 1 and 32 chunks"); + } // due to types we will wing it: - ChunkPos target = new ChunkPos(pos); + final ChunkPos target = new ChunkPos(pos); if (ticket == TicketType.PORTAL) // portal + { cc.level().getChunkSource().addRegionTicket(TicketType.PORTAL, target, radius, pos); + } else if (ticket == TicketType.POST_TELEPORT) // post teleport + { cc.level().getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, target, radius, 1); + } else + { cc.level().getChunkSource().addRegionTicket(TicketType.UNKNOWN, target, radius, target); + } return new NumericValue(ticket.timeout()); }); expression.addContextFunction("sample_noise", -1, (c, t, lv) -> { final CarpetContext cc = (CarpetContext) c; - if (lv.size() == 0) { + if (lv.size() == 0) + { return ListValue.wrap(cc.registry(Registries.DENSITY_FUNCTION).keySet().stream().map(ValueConversions::of)); } final ServerLevel level = cc.level(); final BlockArgument locator = BlockArgument.findIn(cc, lv, 0); final BlockPos pos = locator.block.getPos(); final String[] densityFunctionQueries = lv.stream().skip(locator.offset).map(Value::getString).toArray(String[]::new); - if (densityFunctionQueries.length == 0) { + if (densityFunctionQueries.length == 0) + { return ListValue.wrap(cc.registry(Registries.DENSITY_FUNCTION).keySet().stream().map(ValueConversions::of)); } - NoiseRouter router = level.getChunkSource().randomState().router(); - if (densityFunctionQueries.length == 1) { - return NumericValue.of(sampleNoise(router, level, densityFunctionQueries[0], pos)); - } - return ListValue.wrap(Arrays.stream(densityFunctionQueries).map(s -> NumericValue.of(sampleNoise(router, level, s, pos)))); + final NoiseRouter router = level.getChunkSource().randomState().router(); + return densityFunctionQueries.length == 1 + ? NumericValue.of(sampleNoise(router, level, densityFunctionQueries[0], pos)) + : ListValue.wrap(Arrays.stream(densityFunctionQueries).map(s -> NumericValue.of(sampleNoise(router, level, s, pos)))); }); } - public static double sampleNoise(NoiseRouter router, ServerLevel level, String what, BlockPos pos) { - DensityFunction densityFunction = switch (what) { + public static double sampleNoise(final NoiseRouter router, final ServerLevel level, final String what, final BlockPos pos) + { + final DensityFunction densityFunction = switch (what) + { case "barrier_noise" -> router.barrierNoise(); case "fluid_level_floodedness_noise" -> router.fluidLevelFloodednessNoise(); case "fluid_level_spread_noise" -> router.fluidLevelSpreadNoise(); @@ -1672,21 +1762,6 @@ public class WorldAccess { case "vein_ridged" -> router.veinRidged(); case "vein_gap" -> router.veinGap(); default -> stupidWorldgenNoiseCacheGetter.apply(Pair.of(level, what)); - /*ResourceLocation densityFunctionKey = InputValidator.identifierOf(what); - Registry densityFunctionRegistry = level.registryAccess().registryOrThrow(Registries.DENSITY_FUNCTION); - if (densityFunctionRegistry.containsKey(densityFunctionKey) && level.getChunkSource().getGenerator() instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { - DensityFunction densityFunction1 = densityFunctionRegistry.get(densityFunctionKey); - RandomState randomState = RandomState.create( - noiseBasedChunkGenerator.generatorSettings().value(), - level.registryAccess().lookupOrThrow(Registries.NOISE), level.getSeed() - ); - DensityFunction.Visitor visitor = ((RandomStateVisitorAccessor) (Object) randomState).getVisitor(); - - DensityFunction temp = densityFunction.mapAll(visitor); - } - - throw new InternalExpressionException("Density function '" + what + "' is not defined in the registies.");*/ - }; return densityFunction.compute(new DensityFunction.SinglePointContext(pos.getX(), pos.getY(), pos.getZ())); } @@ -1697,35 +1772,38 @@ public class WorldAccess { String densityFunctionQuery = pair.getValue(); ChunkGenerator generator = level.getChunkSource().getGenerator(); - if (generator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { + if (generator instanceof final NoiseBasedChunkGenerator noiseBasedChunkGenerator) + { Registry densityFunctionRegistry = level.registryAccess().registryOrThrow(Registries.DENSITY_FUNCTION); final NoiseRouter router = noiseBasedChunkGenerator.generatorSettings().value().noiseRouter(); - DensityFunction densityFunction = switch (densityFunctionQuery) { - case "barrier_noise" -> router.barrierNoise(); - case "fluid_level_floodedness_noise" -> router.fluidLevelFloodednessNoise(); - case "fluid_level_spread_noise" -> router.fluidLevelSpreadNoise(); - case "lava_noise" -> router.lavaNoise(); - case "temperature" -> router.temperature(); - case "vegetation" -> router.vegetation(); - case "continents" -> router.continents(); - case "erosion" -> router.erosion(); - case "depth" -> router.depth(); - case "ridges" -> router.ridges(); - case "initial_density_without_jaggedness" -> router.initialDensityWithoutJaggedness(); - case "final_density" -> router.finalDensity(); - case "vein_toggle" -> router.veinToggle(); - case "vein_ridged" -> router.veinRidged(); - case "vein_gap" -> router.veinGap(); - default -> { - ResourceLocation densityFunctionKey = InputValidator.identifierOf(densityFunctionQuery); + DensityFunction densityFunction = switch (densityFunctionQuery) + { + case "barrier_noise" -> router.barrierNoise(); + case "fluid_level_floodedness_noise" -> router.fluidLevelFloodednessNoise(); + case "fluid_level_spread_noise" -> router.fluidLevelSpreadNoise(); + case "lava_noise" -> router.lavaNoise(); + case "temperature" -> router.temperature(); + case "vegetation" -> router.vegetation(); + case "continents" -> router.continents(); + case "erosion" -> router.erosion(); + case "depth" -> router.depth(); + case "ridges" -> router.ridges(); + case "initial_density_without_jaggedness" -> router.initialDensityWithoutJaggedness(); + case "final_density" -> router.finalDensity(); + case "vein_toggle" -> router.veinToggle(); + case "vein_ridged" -> router.veinRidged(); + case "vein_gap" -> router.veinGap(); + default -> { + ResourceLocation densityFunctionKey = InputValidator.identifierOf(densityFunctionQuery); - if (densityFunctionRegistry.containsKey(densityFunctionKey)) { - yield densityFunctionRegistry.get(densityFunctionKey); - } + if (densityFunctionRegistry.containsKey(densityFunctionKey)) + { + yield densityFunctionRegistry.get(densityFunctionKey); + } - throw new InternalExpressionException("Density function '" + densityFunctionQuery + "' is not defined in the registies."); - } - }; + throw new InternalExpressionException("Density function '" + densityFunctionQuery + "' is not defined in the registies."); + } + }; RandomState randomState = RandomState.create( noiseBasedChunkGenerator.generatorSettings().value(), @@ -1733,9 +1811,7 @@ public class WorldAccess { ); DensityFunction.Visitor visitor = ((RandomStateVisitorAccessor) (Object) randomState).getVisitor(); - DensityFunction temp = densityFunction.mapAll(visitor); - - return temp; + return densityFunction.mapAll(visitor); } return DensityFunctions.zero(); }); diff --git a/src/main/java/carpet/script/argument/Argument.java b/src/main/java/carpet/script/argument/Argument.java index 1a9dbd41..4fac0a37 100644 --- a/src/main/java/carpet/script/argument/Argument.java +++ b/src/main/java/carpet/script/argument/Argument.java @@ -3,6 +3,7 @@ package carpet.script.argument; public abstract class Argument { public int offset; + protected Argument(int offset) { this.offset = offset; diff --git a/src/main/java/carpet/script/argument/BlockArgument.java b/src/main/java/carpet/script/argument/BlockArgument.java index b2e66c93..4641b48d 100644 --- a/src/main/java/carpet/script/argument/BlockArgument.java +++ b/src/main/java/carpet/script/argument/BlockArgument.java @@ -7,48 +7,52 @@ import carpet.script.value.ListValue; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; + import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; + import net.minecraft.core.BlockPos; public class BlockArgument extends Argument { public final BlockValue block; public final String replacement; - private BlockArgument(BlockValue b, int o) + + private BlockArgument(final BlockValue b, final int o) { super(o); block = b; replacement = null; } - private BlockArgument(BlockValue b, int o, String replacement) + + private BlockArgument(final BlockValue b, final int o, final String replacement) { super(o); block = b; this.replacement = replacement; } - public static BlockArgument findIn(CarpetContext c, List params, int offset) + public static BlockArgument findIn(final CarpetContext c, final List params, final int offset) { - return findIn(c, params,offset, false, false, false); + return findIn(c, params, offset, false, false, false); } - public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString) + public static BlockArgument findIn(final CarpetContext c, final List params, final int offset, final boolean acceptString) { - return findIn(c, params,offset, acceptString, false, false); + return findIn(c, params, offset, acceptString, false, false); } - public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString, boolean optional, boolean anyString) + public static BlockArgument findIn(final CarpetContext c, final List params, final int offset, final boolean acceptString, final boolean optional, final boolean anyString) { return findIn(c, params.listIterator(offset), offset, acceptString, optional, anyString); } - public static BlockArgument findIn(CarpetContext c, Iterator params, int offset, boolean acceptString, boolean optional, boolean anyString) + public static BlockArgument findIn(final CarpetContext c, final Iterator params, final int offset, final boolean acceptString, final boolean optional, final boolean anyString) { try { - Value v1 = params.next(); + final Value v1 = params.next(); //add conditional from string name if (optional && v1.isNull()) { @@ -69,10 +73,10 @@ public class BlockArgument extends Argument final BlockPos pos = c.origin(); if (v1 instanceof ListValue) { - List args = ((ListValue) v1).getItems(); - int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); - int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); - int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); + final List args = ((ListValue) v1).getItems(); + final int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); + final int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); + final int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); return new BlockArgument( new BlockValue( @@ -82,9 +86,9 @@ public class BlockArgument extends Argument ), 1 + offset); } - int xpos = (int) NumericValue.asNumber(v1).getLong(); - int ypos = (int) NumericValue.asNumber( params.next()).getLong(); - int zpos = (int) NumericValue.asNumber( params.next()).getLong(); + final int xpos = (int) NumericValue.asNumber(v1).getLong(); + final int ypos = (int) NumericValue.asNumber(params.next()).getLong(); + final int zpos = (int) NumericValue.asNumber(params.next()).getLong(); return new BlockArgument( new BlockValue( null, @@ -100,13 +104,17 @@ public class BlockArgument extends Argument } } - private static InternalExpressionException handleError(boolean optional, boolean acceptString) + private static InternalExpressionException handleError(final boolean optional, final boolean acceptString) { String message = "Block-type argument should be defined either by three coordinates (a triple or by three arguments), or a block value"; if (acceptString) - message+=", or a string with block description"; + { + message += ", or a string with block description"; + } if (optional) - message+=", or null"; + { + message += ", or null"; + } return new InternalExpressionException(message); } diff --git a/src/main/java/carpet/script/argument/FileArgument.java b/src/main/java/carpet/script/argument/FileArgument.java index e95ec6f8..835c61ab 100644 --- a/src/main/java/carpet/script/argument/FileArgument.java +++ b/src/main/java/carpet/script/argument/FileArgument.java @@ -59,14 +59,19 @@ public class FileArgument private FileSystem zfs; private Path zipPath; - public final static Object writeIOSync = new Object(); + public static final Object writeIOSync = new Object(); - public void close() { - if (zfs != null && zfs.isOpen()) { - try { + public void close() + { + if (zfs != null && zfs.isOpen()) + { + try + { zfs.close(); - } catch (IOException e) { - throw new InternalExpressionException("Unable to close zip container: "+zipContainer); + } + catch (final IOException e) + { + throw new InternalExpressionException("Unable to close zip container: " + zipContainer); } zfs = null; } @@ -86,10 +91,10 @@ public class FileArgument public static Map of = Arrays.stream(values()).collect(Collectors.toMap(t -> t.id, t -> t)); - Type(String id, String extension) + Type(final String id, final String extension) { - this.id = id; - this.extension = extension; + this.id = id; + this.extension = extension; } } @@ -98,7 +103,7 @@ public class FileArgument READ, CREATE, DELETE } - public FileArgument(String resource, Type type, String zipContainer, boolean isFolder, boolean isShared, Reason reason) + public FileArgument(final String resource, final Type type, final String zipContainer, final boolean isFolder, final boolean isShared, final Reason reason) { this.resource = resource; this.type = type; @@ -111,48 +116,68 @@ public class FileArgument } @Override - public String toString() { - return "path: "+resource+" zip: "+zipContainer+" type: "+type.id+" folder: "+isFolder+" shared: "+isShared+" reason: "+reason.toString(); + public String toString() + { + return "path: " + resource + " zip: " + zipContainer + " type: " + type.id + " folder: " + isFolder + " shared: " + isShared + " reason: " + reason.toString(); } - public static FileArgument from(List lv, boolean isFolder, Reason reason) + public static FileArgument from(final List lv, final boolean isFolder, final Reason reason) { - if (lv.size() < 2) throw new InternalExpressionException("File functions require path and type as first two arguments"); - String origtype = lv.get(1).getString().toLowerCase(Locale.ROOT); - boolean shared = origtype.startsWith("shared_"); - String typeString = shared ? origtype.substring(7) : origtype; //len(shared_) - Type type = Type.of.get(typeString); - Pair resource = recognizeResource(lv.get(0).getString(), isFolder, type); - if (type==null) - throw new InternalExpressionException("Unsupported file type: "+origtype); - if (type==Type.FOLDER && !isFolder) + if (lv.size() < 2) + { + throw new InternalExpressionException("File functions require path and type as first two arguments"); + } + final String origtype = lv.get(1).getString().toLowerCase(Locale.ROOT); + final boolean shared = origtype.startsWith("shared_"); + final String typeString = shared ? origtype.substring(7) : origtype; //len(shared_) + final Type type = Type.of.get(typeString); + final Pair resource = recognizeResource(lv.get(0).getString(), isFolder, type); + if (type == null) + { + throw new InternalExpressionException("Unsupported file type: " + origtype); + } + if (type == Type.FOLDER && !isFolder) + { throw new InternalExpressionException("Folder types are no supported for this IO function"); - return new FileArgument(resource.getLeft(), type,resource.getRight(), isFolder, shared, reason); + } + return new FileArgument(resource.getLeft(), type, resource.getRight(), isFolder, shared, reason); } - public static FileArgument resourceFromPath(String path, Reason reason, boolean shared) + public static FileArgument resourceFromPath(final String path, final Reason reason, final boolean shared) { - Pair resource = recognizeResource(path, false, Type.ANY); - return new FileArgument(resource.getLeft(), Type.ANY,resource.getRight(), false, shared, reason); + final Pair resource = recognizeResource(path, false, Type.ANY); + return new FileArgument(resource.getLeft(), Type.ANY, resource.getRight(), false, shared, reason); } - public static Pair recognizeResource(String origfile, boolean isFolder, Type type) + public static Pair recognizeResource(final String origfile, final boolean isFolder, final Type type) { - String[] pathElements = origfile.split("[/\\\\]+"); - List path = new ArrayList<>(); + final String[] pathElements = origfile.split("[/\\\\]+"); + final List path = new ArrayList<>(); String zipPath = null; - for (int i =0; i < pathElements.length; i++ ) + for (int i = 0; i < pathElements.length; i++) { String token = pathElements[i]; - boolean isZip = token.endsWith(".zip") && (isFolder || (i < pathElements.length-1)); - if (zipPath != null && isZip) throw new InternalExpressionException(token+" indicates zip access in an already zipped location "+zipPath); - if (isZip) token = token.substring(0, token.length()-4); - token = (type==Type.ANY && i == pathElements.length-1)? // sloppy really, but should work - token.replaceAll("[^A-Za-z0-9\\-+_.]", ""): + final boolean isZip = token.endsWith(".zip") && (isFolder || (i < pathElements.length - 1)); + if (zipPath != null && isZip) + { + throw new InternalExpressionException(token + " indicates zip access in an already zipped location " + zipPath); + } + if (isZip) + { + token = token.substring(0, token.length() - 4); + } + token = (type == Type.ANY && i == pathElements.length - 1) ? // sloppy really, but should work + token.replaceAll("[^A-Za-z0-9\\-+_.]", "") : token.replaceAll("[^A-Za-z0-9\\-+_]", ""); - if (token.isEmpty()) continue; - if (isZip) token = token + ".zip"; + if (token.isEmpty()) + { + continue; + } + if (isZip) + { + token = token + ".zip"; + } path.add(token); if (isZip) { @@ -161,80 +186,106 @@ public class FileArgument } } if (path.isEmpty() && !isFolder) + { throw new InternalExpressionException( - "Cannot use "+origfile+" as resource name: indicated path is empty"+((zipPath==null)?"":" in zip container "+zipPath) + "Cannot use " + origfile + " as resource name: indicated path is empty" + ((zipPath == null) ? "" : " in zip container " + zipPath) ); + } return Pair.of(String.join("/", path), zipPath); } - private Path resolve(String suffix) + private Path resolve(final String suffix) { if (CarpetServer.minecraft_server == null) + { throw new InternalExpressionException("Accessing world files without server running"); - return CarpetServer.minecraft_server.getWorldPath(LevelResource.ROOT).resolve("scripts/"+suffix); + } + return CarpetServer.minecraft_server.getWorldPath(LevelResource.ROOT).resolve("scripts/" + suffix); } - private Path toPath(Module module) + private Path toPath(final Module module) { - if (!isShared && module == null) return null; + if (!isShared && module == null) + { + return null; + } if (zipContainer == null) - return resolve(getDescriptor(module, resource)+(isFolder?"":type.extension)); + { + return resolve(getDescriptor(module, resource) + (isFolder ? "" : type.extension)); + } else { if (zfs == null) { - Map env = new HashMap<>(); - if (reason == Reason.CREATE) env.put("create", "true"); - zipPath = resolve(getDescriptor(module, zipContainer)); - if (!Files.exists(zipPath) && reason != Reason.CREATE) return null; // no zip file - try { - if (!Files.exists(zipPath.getParent())) Files.createDirectories(zipPath.getParent()); - zfs = FileSystems.newFileSystem(URI.create("jar:"+ zipPath.toUri().toString()), env); + final Map env = new HashMap<>(); + if (reason == Reason.CREATE) + { + env.put("create", "true"); } - catch (FileSystemNotFoundException | IOException e) + zipPath = resolve(getDescriptor(module, zipContainer)); + if (!Files.exists(zipPath) && reason != Reason.CREATE) + { + return null; // no zip file + } + try + { + if (!Files.exists(zipPath.getParent())) + { + Files.createDirectories(zipPath.getParent()); + } + zfs = FileSystems.newFileSystem(URI.create("jar:" + zipPath.toUri()), env); + } + catch (final FileSystemNotFoundException | IOException e) { CarpetScriptServer.LOG.warn("Exception when opening zip file", e); - throw new ThrowStatement("Unable to open zip file: "+zipContainer, Throwables.IO_EXCEPTION); + throw new ThrowStatement("Unable to open zip file: " + zipContainer, Throwables.IO_EXCEPTION); } } - return zfs.getPath(resource+(isFolder?"/":type.extension)); + return zfs.getPath(resource + (isFolder ? "/" : type.extension)); } } - private Path moduleRootPath(Module module) + private Path moduleRootPath(final Module module) { - if (!isShared && module == null) return null; - return resolve(isShared?"shared":module.name()+".data"); + return !isShared && module == null + ? null + : resolve(isShared ? "shared" : module.name() + ".data"); } public String getDisplayPath() { - return (isShared?"shared/":"")+(zipContainer!=null?zipContainer+"/":"")+resource+type.extension; + return (isShared ? "shared/" : "") + (zipContainer != null ? zipContainer + "/" : "") + resource + type.extension; } - private String getDescriptor(Module module, String res) + private String getDescriptor(final Module module, final String res) { if (isShared) { - return res.isEmpty()?"shared":"shared/"+res; + return res.isEmpty() ? "shared" : "shared/" + res; } if (module != null) // appdata { - return module.name()+".data"+(res==null || res.isEmpty()?"":"/"+res); + return module.name() + ".data" + (res == null || res.isEmpty() ? "" : "/" + res); } - throw new InternalExpressionException("Invalid file descriptor: "+res); + throw new InternalExpressionException("Invalid file descriptor: " + res); } - public boolean findPathAndApply(Module module, Consumer action) + public boolean findPathAndApply(final Module module, final Consumer action) { - try { synchronized (writeIOSync) + try { - Path dataFile = toPath(module);//, resourceName, supportedTypes.get(type), isShared); - if (dataFile == null) return false; - createPaths(dataFile); - action.accept(dataFile); - } } + synchronized (writeIOSync) + { + final Path dataFile = toPath(module);//, resourceName, supportedTypes.get(type), isShared); + if (dataFile == null) + { + return false; + } + createPaths(dataFile); + action.accept(dataFile); + } + } finally { close(); @@ -242,83 +293,109 @@ public class FileArgument return true; } - public Stream listFiles(Module module) + public Stream listFiles(final Module module) { - Path dir = toPath(module); - if (dir == null || !Files.exists(dir)) return null; - String ext = type.extension; + final Path dir = toPath(module); + if (dir == null || !Files.exists(dir)) + { + return null; + } + final String ext = type.extension; try { - return Files.list(dir).filter(path -> (type==Type.FOLDER) - ?Files.isDirectory(path) - :(Files.isRegularFile(path) && path.toString().endsWith(ext)) + return Files.list(dir).filter(path -> (type == Type.FOLDER) + ? Files.isDirectory(path) + : (Files.isRegularFile(path) && path.toString().endsWith(ext)) ); } - catch (IOException ignored) + catch (final IOException ignored) { return null; } } - public Stream listFolder(Module module) + public Stream listFolder(final Module module) { Stream strings; - try (Stream result = listFiles(module)) { synchronized (writeIOSync) + try (final Stream result = listFiles(module)) { - if (result == null) return null; - Path rootPath = moduleRootPath(module); - if (rootPath == null) return null; - String zipComponent = (zipContainer != null) ? rootPath.relativize(zipPath).toString() : null; - // need to evaluate the stream before exiting try-with-resources else there'll be no data to stream - strings = (zipContainer == null) - ? result.map(p -> rootPath.relativize(p).toString().replaceAll("[\\\\/]+", "/")).toList().stream() - : result.map(p -> (zipComponent + '/'+ p.toString()).replaceAll("[\\\\/]+", "/")).toList().stream(); - } } + synchronized (writeIOSync) + { + if (result == null) + { + return null; + } + final Path rootPath = moduleRootPath(module); + if (rootPath == null) + { + return null; + } + final String zipComponent = (zipContainer != null) ? rootPath.relativize(zipPath).toString() : null; + // need to evaluate the stream before exiting try-with-resources else there'll be no data to stream + strings = (zipContainer == null) + ? result.map(p -> rootPath.relativize(p).toString().replaceAll("[\\\\/]+", "/")).toList().stream() + : result.map(p -> (zipComponent + '/' + p.toString()).replaceAll("[\\\\/]+", "/")).toList().stream(); + } + } finally { close(); } - if (type == Type.FOLDER) - // java 8 paths are inconsistent. in java 16 they all should not have trailing slashes - return strings.map(s -> s.endsWith("/")?s.substring(0, s.length()-1):s); - return strings.map(FilenameUtils::removeExtension); + // java 8 paths are inconsistent. in java 16 they all should not have trailing slashes + return type == Type.FOLDER + ? strings.map(s -> s.endsWith("/") ? s.substring(0, s.length() - 1) : s) + : strings.map(FilenameUtils::removeExtension); } - private void createPaths(Path file) + private void createPaths(final Path file) { - try { + try + { if ((zipContainer == null || file.getParent() != null) && !Files.exists(file.getParent()) && Files.createDirectories(file.getParent()) == null - ) throw new IOException(); - } catch (IOException e) { + ) + { + throw new IOException(); + } + } + catch (final IOException e) + { CarpetScriptServer.LOG.warn("IOException when creating paths", e); - throw new ThrowStatement("Unable to create paths for "+file.toString(), Throwables.IO_EXCEPTION); + throw new ThrowStatement("Unable to create paths for " + file, Throwables.IO_EXCEPTION); } - } - public boolean appendToTextFile(Module module, List message) + public boolean appendToTextFile(final Module module, final List message) { - try { synchronized (writeIOSync) + try { - Path dataFile = toPath(module);//, resourceName, supportedTypes.get(type), isShared); - if (dataFile == null) return false; - createPaths(dataFile); - OutputStream out = Files.newOutputStream(dataFile, StandardOpenOption.APPEND, StandardOpenOption.CREATE); - try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))) + synchronized (writeIOSync) { - for (String line: message) + final Path dataFile = toPath(module); + if (dataFile == null) { - writer.append(line); - if (type == Type.TEXT) writer.newLine(); + return false; + } + createPaths(dataFile); + final OutputStream out = Files.newOutputStream(dataFile, StandardOpenOption.APPEND, StandardOpenOption.CREATE); + try (final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))) + { + for (final String line : message) + { + writer.append(line); + if (type == Type.TEXT) + { + writer.newLine(); + } + } } } - } } - catch (IOException e) + } + catch (final IOException e) { CarpetScriptServer.LOG.warn("IOException when appending to text file", e); - throw new ThrowStatement("Error when writing to the file: "+e, Throwables.IO_EXCEPTION); + throw new ThrowStatement("Error when writing to the file: " + e, Throwables.IO_EXCEPTION); } finally { @@ -327,76 +404,91 @@ public class FileArgument return true; } - public Tag getNbtData(Module module) // aka getData + public Tag getNbtData(final Module module) // aka getData { - try { synchronized (writeIOSync) { - Path dataFile = toPath(module); - if (dataFile == null || !Files.exists(dataFile)) return null; - return readTag(dataFile); - } } - finally { + try + { + synchronized (writeIOSync) + { + final Path dataFile = toPath(module); + if (dataFile == null || !Files.exists(dataFile)) + { + return null; + } + return readTag(dataFile); + } + } + finally + { close(); } } //copied private method from net.minecraft.nbt.NbtIo.read() // to read non-compound tags - these won't be compressed - public static Tag readTag(Path path) + public static Tag readTag(final Path path) { try { return NbtIo.readCompressed(Files.newInputStream(path)); } - catch (IOException e) + catch (final IOException e) { // Copy of NbtIo.read(File) because that's now client-side only if (!Files.exists(path)) { return null; } - try (DataInputStream in = new DataInputStream(new BufferedInputStream(Files.newInputStream(path)))) + try (final DataInputStream in = new DataInputStream(new BufferedInputStream(Files.newInputStream(path)))) { return NbtIo.read(in); } - catch (IOException ioException) + catch (final IOException ioException) { // not compressed compound tag neither uncompressed compound tag - trying any type of a tag - try (DataInputStream dataInput_1 = new DataInputStream(new BufferedInputStream(Files.newInputStream(path)))) + try (final DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(Files.newInputStream(path)))) { - byte byte_1 = dataInput_1.readByte(); - if (byte_1 == 0) + final byte b = dataInputStream.readByte(); + if (b == 0) { return null; } else { - dataInput_1.readUTF(); - return TagTypes.getType(byte_1).load(dataInput_1, 0, NbtAccounter.UNLIMITED); + dataInputStream.readUTF(); + return TagTypes.getType(b).load(dataInputStream, 0, NbtAccounter.UNLIMITED); } } - catch (IOException secondIO) + catch (final IOException secondIO) { CarpetScriptServer.LOG.warn("IOException when trying to read nbt file, something may have gone wrong with the fs", e); CarpetScriptServer.LOG.warn("", ioException); CarpetScriptServer.LOG.warn("", secondIO); - throw new ThrowStatement("Not a valid NBT tag in "+path.toString(), Throwables.NBT_ERROR); + throw new ThrowStatement("Not a valid NBT tag in " + path, Throwables.NBT_ERROR); } } } - catch (ReportedException e) + catch (final ReportedException e) { - throw new ThrowStatement("Error when reading NBT file "+path.toString(), Throwables.NBT_ERROR); + throw new ThrowStatement("Error when reading NBT file " + path.toString(), Throwables.NBT_ERROR); } } - public boolean saveNbtData(Module module, Tag tag) // aka saveData + public boolean saveNbtData(final Module module, final Tag tag) // aka saveData { - try { synchronized (writeIOSync) { - Path dataFile = toPath(module); - if (dataFile == null) return false; - createPaths(dataFile); - return writeTagDisk(tag, dataFile, zipContainer != null); - } } + try + { + synchronized (writeIOSync) + { + final Path dataFile = toPath(module); + if (dataFile == null) + { + return false; + } + createPaths(dataFile); + return writeTagDisk(tag, dataFile, zipContainer != null); + } + } finally { close(); @@ -404,9 +496,9 @@ public class FileArgument } //copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write - public static boolean writeTagDisk(Tag tag_1, Path path, boolean zipped) + public static boolean writeTagDisk(final Tag tag, Path path, final boolean zipped) { - Path original = path; + final Path original = path; try { if (!zipped) @@ -415,19 +507,19 @@ public class FileArgument Files.deleteIfExists(path); } - if (tag_1 instanceof CompoundTag) + if (tag instanceof final CompoundTag cTag) { - NbtIo.writeCompressed((CompoundTag) tag_1, Files.newOutputStream(path)); + NbtIo.writeCompressed(cTag, Files.newOutputStream(path)); } else { - try (DataOutputStream dataOutputStream_1 = new DataOutputStream(Files.newOutputStream(path))) + try (final DataOutputStream dataOutputStream = new DataOutputStream(Files.newOutputStream(path))) { - dataOutputStream_1.writeByte(tag_1.getId()); - if (tag_1.getId() != 0) + dataOutputStream.writeByte(tag.getId()); + if (tag.getId() != 0) { - dataOutputStream_1.writeUTF(""); - tag_1.write(dataOutputStream_1); + dataOutputStream.writeUTF(""); + tag.write(dataOutputStream); } } } @@ -438,26 +530,31 @@ public class FileArgument } return true; } - catch (IOException e) + catch (final IOException e) { CarpetScriptServer.LOG.warn("IO Exception when writing nbt file", e); - throw new ThrowStatement("Unable to write tag to "+original.toString(), Throwables.IO_EXCEPTION); + throw new ThrowStatement("Unable to write tag to " + original, Throwables.IO_EXCEPTION); } } - public boolean dropExistingFile(Module module) + public boolean dropExistingFile(final Module module) { - - try { synchronized (writeIOSync) + try { - Path dataFile = toPath(module); - if (dataFile == null) return false; - return Files.deleteIfExists(dataFile); - } } - catch (IOException e) + synchronized (writeIOSync) + { + final Path dataFile = toPath(module); + if (dataFile == null) + { + return false; + } + return Files.deleteIfExists(dataFile); + } + } + catch (final IOException e) { CarpetScriptServer.LOG.warn("IOException when removing file", e); - throw new ThrowStatement("Error while removing file: "+getDisplayPath(), Throwables.IO_EXCEPTION); + throw new ThrowStatement("Error while removing file: " + getDisplayPath(), Throwables.IO_EXCEPTION); } finally { @@ -465,69 +562,95 @@ public class FileArgument } } - public List listFile(Module module) + public List listFile(final Module module) { - try { synchronized (writeIOSync) { - Path dataFile = toPath(module); - if (dataFile == null) return null; - if (!Files.exists(dataFile)) return null; - return listFileContent(dataFile); - } } - finally { + try + { + synchronized (writeIOSync) + { + final Path dataFile = toPath(module); + if (dataFile == null) + { + return null; + } + if (!Files.exists(dataFile)) + { + return null; + } + return listFileContent(dataFile); + } + } + finally + { close(); } } - public static List listFileContent(Path filePath) + public static List listFileContent(final Path filePath) { - try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) { - List result = new ArrayList<>(); - for (;;) { - String line = reader.readLine(); + try (final BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) + { + final List result = new ArrayList<>(); + for (; ; ) + { + final String line = reader.readLine(); if (line == null) + { break; - result.add(line.replaceAll("[\n\r]+","")); + } + result.add(line.replaceAll("[\n\r]+", "")); } return result; } - catch (IOException e) + catch (final IOException e) { CarpetScriptServer.LOG.warn("IOException when reading text file", e); - throw new ThrowStatement("Failed to read text file "+filePath.toString(), Throwables.IO_EXCEPTION); + throw new ThrowStatement("Failed to read text file " + filePath, Throwables.IO_EXCEPTION); } } - public JsonElement readJsonFile(Module module) { - try { synchronized (writeIOSync) { - Path dataFile = toPath(module); - if (dataFile == null || !Files.exists(dataFile)) return null; - return readJsonContent(dataFile); - } } - finally { + public JsonElement readJsonFile(final Module module) + { + try + { + synchronized (writeIOSync) + { + final Path dataFile = toPath(module); + if (dataFile == null || !Files.exists(dataFile)) + { + return null; + } + return readJsonContent(dataFile); + } + } + finally + { close(); } } - public static JsonElement readJsonContent(Path filePath) + public static JsonElement readJsonContent(final Path filePath) { - try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) + try (final BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) { return JsonParser.parseReader(reader); } - catch (JsonParseException e) + catch (final JsonParseException e) { Throwable exc = e; - if(e.getCause() != null) + if (e.getCause() != null) + { exc = e.getCause(); + } throw new ThrowStatement(MapValue.wrap(Map.of( StringValue.of("error"), StringValue.of(exc.getMessage()), StringValue.of("path"), StringValue.of(filePath.toString()) )), Throwables.JSON_ERROR); } - catch (IOException e) + catch (final IOException e) { CarpetScriptServer.LOG.warn("IOException when reading JSON file", e); - throw new ThrowStatement("Failed to read json file content "+filePath.toString(), Throwables.IO_EXCEPTION); + throw new ThrowStatement("Failed to read json file content " + filePath, Throwables.IO_EXCEPTION); } } diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java index 387cc66e..eb19526f 100644 --- a/src/main/java/carpet/script/argument/FunctionArgument.java +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -19,7 +19,7 @@ public class FunctionArgument extends Argument public FunctionValue function; public List args; - private FunctionArgument(FunctionValue function, int offset, List args) + private FunctionArgument(final FunctionValue function, final int offset, final List args) { super(offset); this.function = function; @@ -27,10 +27,10 @@ public class FunctionArgument extends Argument } /** - * @param c context - * @param module module - * @param params list of params - * @param offset offset where to start looking for functional argument + * @param c context + * @param module module + * @param params list of params + * @param offset offset where to start looking for functional argument * @param allowNone none indicates no function present, otherwise it will croak * @param checkArgs whether the caller expects trailing parameters to fully resolve function argument list * if not - argument count check will not be performed and its up to the caller to verify @@ -38,63 +38,85 @@ public class FunctionArgument extends Argument * @return argument data */ public static FunctionArgument findIn( - Context c, - Module module, - List params, - int offset, - boolean allowNone, - boolean checkArgs) + final Context c, + final Module module, + final List params, + final int offset, + final boolean allowNone, + final boolean checkArgs) { Value functionValue = params.get(offset); if (functionValue.isNull()) { - if (allowNone) return new FunctionArgument(null, offset+1, Collections.emptyList()); + if (allowNone) + { + return new FunctionArgument(null, offset + 1, Collections.emptyList()); + } throw new InternalExpressionException("function argument cannot be null"); } if (!(functionValue instanceof FunctionValue)) { - String name = functionValue.getString(); + final String name = functionValue.getString(); functionValue = c.host.getAssertFunction(module, name); } - FunctionValue fun = (FunctionValue)functionValue; - int argsize = fun.getArguments().size(); + final FunctionValue fun = (FunctionValue) functionValue; + final int argsize = fun.getArguments().size(); if (checkArgs) { - int extraargs = params.size() - argsize - offset - 1; + final int extraargs = params.size() - argsize - offset - 1; if (extraargs < 0) + { throw new InternalExpressionException("Function " + fun.getPrettyString() + " requires at least " + fun.getArguments().size() + " arguments"); + } if (extraargs > 0 && fun.getVarArgs() == null) + { throw new InternalExpressionException("Function " + fun.getPrettyString() + " requires " + fun.getArguments().size() + " arguments"); + } + } + final List lvargs = new ArrayList<>(); + for (int i = offset + 1, mx = params.size(); i < mx; i++) + { + lvargs.add(params.get(i)); } - List lvargs = new ArrayList<>(); - for (int i = offset+1, mx = params.size(); i < mx; i++) lvargs.add(params.get(i)); return new FunctionArgument(fun, offset + 1 + argsize, lvargs); } - public static FunctionArgument fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException { - FunctionValue function; + public static FunctionArgument fromCommandSpec(final ScriptHost host, Value funSpec) throws CommandSyntaxException + { + final FunctionValue function; List args = Collections.emptyList(); if (!(funSpec instanceof ListValue)) + { funSpec = ListValue.of(funSpec); - List params = ((ListValue) funSpec).getItems(); - if (params.isEmpty()) throw CommandArgument.error("Function has empty spec"); - Value first = params.get(0); + } + final List params = ((ListValue) funSpec).getItems(); + if (params.isEmpty()) + { + throw CommandArgument.error("Function has empty spec"); + } + final Value first = params.get(0); if (first instanceof FunctionValue) { - function = (FunctionValue)first; + function = (FunctionValue) first; } else { - String name = first.getString(); + final String name = first.getString(); function = host.getFunction(name); - if (function == null) throw CommandArgument.error("Function "+name+" is not defined yet"); + if (function == null) + { + throw CommandArgument.error("Function " + name + " is not defined yet"); + } + } + if (params.size() > 1) + { + args = params.subList(1, params.size()); } - if (params.size() > 1) args = params.subList(1,params.size()); - return new FunctionArgument(function, 0, args); } - public List checkedArgs() { + public List checkedArgs() + { function.checkArgs(args.size()); return args; } diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java index c19bb479..f46068e8 100644 --- a/src/main/java/carpet/script/argument/Vector3Argument.java +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -6,9 +6,11 @@ import carpet.script.value.EntityValue; import carpet.script.value.ListValue; import carpet.script.value.NumericValue; import carpet.script.value.Value; + import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; + import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; @@ -19,14 +21,16 @@ public class Vector3Argument extends Argument public final double pitch; public boolean fromBlock = false; public Entity entity = null; - private Vector3Argument(Vec3 v, int o) + + private Vector3Argument(final Vec3 v, final int o) { super(o); this.vec = v; this.yaw = 0.0D; this.pitch = 0.0D; } - private Vector3Argument(Vec3 v, int o, double y, double p) + + private Vector3Argument(final Vec3 v, final int o, final double y, final double p) { super(o); this.vec = v; @@ -40,52 +44,53 @@ public class Vector3Argument extends Argument return this; } - private Vector3Argument withEntity(Entity e) + private Vector3Argument withEntity(final Entity e) { entity = e; return this; } - public static Vector3Argument findIn(List params, int offset) + public static Vector3Argument findIn(final List params, final int offset) { return findIn(params, offset, false, false); } - public static Vector3Argument findIn(List params, int offset, boolean optionalDirection, boolean optionalEntity) { + public static Vector3Argument findIn(final List params, final int offset, final boolean optionalDirection, final boolean optionalEntity) + { return findIn(params.listIterator(offset), offset, optionalDirection, optionalEntity); } - public static Vector3Argument findIn(Iterator params, int offset, boolean optionalDirection, boolean optionalEntity) + public static Vector3Argument findIn(final Iterator params, final int offset, final boolean optionalDirection, final boolean optionalEntity) { try { - Value v1 = params.next(); + final Value v1 = params.next(); if (v1 instanceof BlockValue) { - return (new Vector3Argument(Vec3.atCenterOf(((BlockValue) v1).getPos()), 1+offset)).fromBlock(); + return (new Vector3Argument(Vec3.atCenterOf(((BlockValue) v1).getPos()), 1 + offset)).fromBlock(); } if (optionalEntity && v1 instanceof EntityValue) { - Entity e = ((EntityValue) v1).getEntity(); - return new Vector3Argument(e.position(), 1+offset).withEntity(e); + final Entity e = ((EntityValue) v1).getEntity(); + return new Vector3Argument(e.position(), 1 + offset).withEntity(e); } if (v1 instanceof ListValue) { - List args = ((ListValue) v1).getItems(); - Vec3 pos = new Vec3( + final List args = ((ListValue) v1).getItems(); + final Vec3 pos = new Vec3( NumericValue.asNumber(args.get(0)).getDouble(), NumericValue.asNumber(args.get(1)).getDouble(), NumericValue.asNumber(args.get(2)).getDouble()); double yaw = 0.0D; double pitch = 0.0D; - if (args.size()>3 && optionalDirection) + if (args.size() > 3 && optionalDirection) { yaw = NumericValue.asNumber(args.get(3)).getDouble(); pitch = NumericValue.asNumber(args.get(4)).getDouble(); } - return new Vector3Argument(pos,offset+1, yaw, pitch); + return new Vector3Argument(pos, offset + 1, yaw, pitch); } - Vec3 pos = new Vec3( + final Vec3 pos = new Vec3( NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(params.next()).getDouble(), NumericValue.asNumber(params.next()).getDouble()); @@ -99,9 +104,9 @@ public class Vector3Argument extends Argument eatenLength = 5; } - return new Vector3Argument(pos, offset+eatenLength, yaw, pitch); + return new Vector3Argument(pos, offset + eatenLength, yaw, pitch); } - catch (IndexOutOfBoundsException | NoSuchElementException e) + catch (final IndexOutOfBoundsException | NoSuchElementException e) { throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value"); } diff --git a/src/main/java/carpet/script/command/CommandArgument.java b/src/main/java/carpet/script/command/CommandArgument.java index 5fcd34ba..f0619c74 100644 --- a/src/main/java/carpet/script/command/CommandArgument.java +++ b/src/main/java/carpet/script/command/CommandArgument.java @@ -39,6 +39,7 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.mojang.brigadier.tree.ArgumentCommandNode; import com.mojang.brigadier.tree.CommandNode; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -53,6 +54,7 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; + import net.minecraft.ChatFormatting; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.critereon.MinMaxBounds; @@ -110,36 +112,33 @@ import static net.minecraft.commands.Commands.argument; public abstract class CommandArgument { - public static CommandSyntaxException error(String text) + public static CommandSyntaxException error(final String text) { return new SimpleCommandExceptionType(Component.literal(text)).create(); } - private static final DynamicCommandExceptionType ERROR_BIOME_INVALID = new DynamicCommandExceptionType(v -> Component.translatable("commands.locate.biome.invalid", v)); - - private static final List baseTypes = Lists.newArrayList( // default new StringArgument(), // vanilla arguments as per https://minecraft.gamepedia.com/Argument_types - new VanillaUnconfigurableArgument( "bool", BoolArgumentType::bool, + new VanillaUnconfigurableArgument("bool", BoolArgumentType::bool, (c, p) -> BooleanValue.of(BoolArgumentType.getBool(c, p)), false ), new FloatArgument(), new IntArgument(), new WordArgument(), new GreedyStringArgument(), - new VanillaUnconfigurableArgument( "yaw", AngleArgument::angle, // angle + new VanillaUnconfigurableArgument("yaw", AngleArgument::angle, // angle (c, p) -> new NumericValue(AngleArgument.getAngle(c, p)), true ), new BlockPosArgument(), - new VanillaUnconfigurableArgument( "block", BlockStateArgument::block, + new VanillaUnconfigurableArgument("block", BlockStateArgument::block, (c, p) -> { BlockInput result = BlockStateArgument.getBlock(c, p); - return new BlockValue(result.getState(), c.getSource().getLevel(), null, ((BlockStateArgumentInterface)result).getCMTag() ); + return new BlockValue(result.getState(), c.getSource().getLevel(), null, ((BlockStateArgumentInterface) result).getCMTag()); }, param -> (ctx, builder) -> ctx.getArgument(param, BlockStateArgument.class).listSuggestions(ctx, builder) ), - new VanillaUnconfigurableArgument( "blockpredicate", BlockPredicateArgument::blockPredicate, + new VanillaUnconfigurableArgument("blockpredicate", BlockPredicateArgument::blockPredicate, (c, p) -> ValueConversions.ofBlockPredicate(c.getSource().getServer().registryAccess(), BlockPredicateArgument.getBlockPredicate(c, p)), param -> (ctx, builder) -> ctx.getArgument(param, BlockPredicateArgument.class).listSuggestions(ctx, builder) ), @@ -204,21 +203,21 @@ public abstract class CommandArgument // resource / identifier section new VanillaUnconfigurableArgument("recipe", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of( ResourceLocationArgument.getRecipe(c, p).getId()), SuggestionProviders.ALL_RECIPES + (c, p) -> ValueConversions.of(ResourceLocationArgument.getRecipe(c, p).getId()), SuggestionProviders.ALL_RECIPES ), new VanillaUnconfigurableArgument("advancement", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of( ResourceLocationArgument.getAdvancement(c, p).getId()), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getAdvancements().getAllAdvancements().stream().map(Advancement::getId), builder) + (c, p) -> ValueConversions.of(ResourceLocationArgument.getAdvancement(c, p).getId()), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getAdvancements().getAllAdvancements().stream().map(Advancement::getId), builder) ), new VanillaUnconfigurableArgument("lootcondition", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of( c.getSource().registryAccess().registryOrThrow(Registries.LOOT_CONDITION_TYPE).getKey(ResourceLocationArgument.getPredicate(c, p).getType())), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getPredicateManager().getKeys(), builder) + (c, p) -> ValueConversions.of(c.getSource().registryAccess().registryOrThrow(Registries.LOOT_CONDITION_TYPE).getKey(ResourceLocationArgument.getPredicate(c, p).getType())), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getPredicateManager().getKeys(), builder) ), new VanillaUnconfigurableArgument("loottable", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getLootTables().getIds(), builder) + (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getLootTables().getIds(), builder) ), new VanillaUnconfigurableArgument("attribute", Registries.ATTRIBUTE), new VanillaUnconfigurableArgument("boss", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), BossBarCommands.SUGGEST_BOSS_BAR + (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), BossBarCommands.SUGGEST_BOSS_BAR ), new VanillaUnconfigurableArgument("biome", (c) -> ResourceOrTagArgument.resourceOrTag(c, Registries.BIOME), @@ -237,10 +236,10 @@ public abstract class CommandArgument }, (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().registryAccess().registryOrThrow(Registries.BIOME).keySet(), builder) ), new VanillaUnconfigurableArgument("sound", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), SuggestionProviders.AVAILABLE_SOUNDS + (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), SuggestionProviders.AVAILABLE_SOUNDS ), new VanillaUnconfigurableArgument("storekey", ResourceLocationArgument::id, - (c, p) -> ValueConversions.of( ResourceLocationArgument.getId(c, p)), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getCommandStorage().keys(), builder) + (c, p) -> ValueConversions.of(ResourceLocationArgument.getId(c, p)), (ctx, builder) -> SharedSuggestionProvider.suggestResource(ctx.getSource().getServer().getCommandStorage().keys(), builder) ), // default @@ -286,29 +285,41 @@ public abstract class CommandArgument public static final CommandArgument DEFAULT = baseTypes.get(0); - public static CommandArgument getTypeForArgument(String argument, CarpetScriptHost host) + public static CommandArgument getTypeForArgument(final String argument, final CarpetScriptHost host) { - String[] components = argument.split("_"); + final String[] components = argument.split("_"); CommandArgument arg; for (int i = 0; i < components.length; i++) { - String candidate = String.join("_", Arrays.asList(components).subList(i, components.length)); + final String candidate = String.join("_", Arrays.asList(components).subList(i, components.length)); arg = host.appArgTypes.get(candidate); - if (arg != null) return arg; + if (arg != null) + { + return arg; + } arg = builtIns.get(candidate); - if (arg != null) return arg; + if (arg != null) + { + return arg; + } } return DEFAULT; } - public static RequiredArgumentBuilder argumentNode(String param, CarpetScriptHost host) throws CommandSyntaxException + public static RequiredArgumentBuilder argumentNode(final String param, final CarpetScriptHost host) throws CommandSyntaxException { - CommandArgument arg = getTypeForArgument(param, host); - if (arg.suggestionProvider != null) return argument(param, arg.getArgumentType(host)).suggests(arg.suggestionProvider.apply(param)); - if (!arg.needsMatching) return argument(param, arg.getArgumentType(host)); - String hostName = host.getName(); + final CommandArgument arg = getTypeForArgument(param, host); + if (arg.suggestionProvider != null) + { + return argument(param, arg.getArgumentType(host)).suggests(arg.suggestionProvider.apply(param)); + } + if (!arg.needsMatching) + { + return argument(param, arg.getArgumentType(host)); + } + final String hostName = host.getName(); return argument(param, arg.getArgumentType(host)).suggests((ctx, b) -> { - CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(ctx.getSource()); + final CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveOwnForExecution(ctx.getSource()); return arg.suggest(ctx, b, cHost); }); } @@ -322,9 +333,9 @@ public abstract class CommandArgument protected CommandArgument( - String suffix, - Collection examples, - boolean suggestFromExamples) + final String suffix, + final Collection examples, + final boolean suggestFromExamples) { this.suffix = suffix; this.examples = examples; @@ -334,7 +345,7 @@ public abstract class CommandArgument protected abstract ArgumentType getArgumentType(CarpetScriptHost host) throws CommandSyntaxException; - public static Value getValue(CommandContext context, String param, CarpetScriptHost host) throws CommandSyntaxException + public static Value getValue(final CommandContext context, final String param, final CarpetScriptHost host) throws CommandSyntaxException { return getTypeForArgument(param, host).getValueFromContext(context, param); } @@ -346,20 +357,24 @@ public abstract class CommandArgument return suffix; } - public static CommandArgument buildFromConfig(String suffix, Map config, CarpetScriptHost host) throws CommandSyntaxException + public static CommandArgument buildFromConfig(final String suffix, final Map config, final CarpetScriptHost host) throws CommandSyntaxException { if (!config.containsKey("type")) - throw CommandArgument.error("Custom type "+suffix+" should at least specify the type"); - String baseType = config.get("type").getString(); + { + throw CommandArgument.error("Custom type " + suffix + " should at least specify the type"); + } + final String baseType = config.get("type").getString(); if (!builtIns.containsKey(baseType)) - throw CommandArgument.error("Unknown base type "+baseType+" for custom type "+suffix); - CommandArgument variant = builtIns.get(baseType).factory(host.scriptServer().server).get(); + { + throw CommandArgument.error("Unknown base type " + baseType + " for custom type " + suffix); + } + final CommandArgument variant = builtIns.get(baseType).factory(host.scriptServer().server).get(); variant.suffix = suffix; variant.configure(config, host); return variant; } - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { caseSensitive = config.getOrDefault("case_sensitive", Value.TRUE).getBoolean(); if (config.containsKey("suggester")) @@ -368,74 +383,87 @@ public abstract class CommandArgument } if (config.containsKey("suggest")) { - if (config.containsKey("suggester")) throw error("Attempted to provide 'suggest' list while 'suggester' is present"+" for custom type "+suffix); - Value suggestionValue = config.get("suggest"); - if (!(suggestionValue instanceof ListValue)) throw error("Argument suggestions needs to be a list"+" for custom type "+suffix); + if (config.containsKey("suggester")) + { + throw error("Attempted to provide 'suggest' list while 'suggester' is present" + " for custom type " + suffix); + } + final Value suggestionValue = config.get("suggest"); + if (!(suggestionValue instanceof ListValue)) + { + throw error("Argument suggestions needs to be a list" + " for custom type " + suffix); + } examples = ((ListValue) suggestionValue).getItems().stream() .map(Value::getString) .collect(Collectors.toSet()); - if (!examples.isEmpty()) needsMatching = true; + if (!examples.isEmpty()) + { + needsMatching = true; + } } } public CompletableFuture suggest( - CommandContext context, - SuggestionsBuilder suggestionsBuilder, - CarpetScriptHost host + final CommandContext context, + final SuggestionsBuilder suggestionsBuilder, + final CarpetScriptHost host ) throws CommandSyntaxException { String prefix = suggestionsBuilder.getRemaining(); - if (!caseSensitive) prefix = prefix.toLowerCase(Locale.ROOT); + if (!caseSensitive) + { + prefix = prefix.toLowerCase(Locale.ROOT); + } suggestFor(context, prefix, host).forEach(suggestionsBuilder::suggest); return suggestionsBuilder.buildFuture(); } - protected List suggestFor(CommandContext context, String prefix, CarpetScriptHost host) throws CommandSyntaxException + protected List suggestFor(final CommandContext context, final String prefix, final CarpetScriptHost host) throws CommandSyntaxException { return getOptions(context, host).stream().filter(s -> optionMatchesPrefix(prefix, s)).collect(Collectors.toList()); } - protected Collection getOptions(CommandContext context, CarpetScriptHost host) throws CommandSyntaxException + protected Collection getOptions(final CommandContext context, final CarpetScriptHost host) throws CommandSyntaxException { if (customSuggester != null) { - CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); - Map params = new HashMap<>(); - for(ParsedCommandNode pnode : context.getNodes()) + final CarpetProfiler.ProfilerToken currentSection = CarpetProfiler.start_section(null, "Scarpet command", CarpetProfiler.TYPE.GENERAL); + final Map params = new HashMap<>(); + for (final ParsedCommandNode pnode : context.getNodes()) { - CommandNode node = pnode.getNode(); + final CommandNode node = pnode.getNode(); if (node instanceof ArgumentCommandNode) { params.put(StringValue.of(node.getName()), CommandArgument.getValue(context, node.getName(), host)); } } - List args = new ArrayList<>(customSuggester.args.size()+1); + final List args = new ArrayList<>(customSuggester.args.size() + 1); args.add(MapValue.wrap(params)); args.addAll(customSuggester.args); - Value response = host.handleCommand(context.getSource(), customSuggester.function, args); - if (!(response instanceof ListValue)) throw error("Custom suggester should return a list of options"+" for custom type "+suffix); - Collection res = ((ListValue) response).getItems().stream().map(Value::getString).collect(Collectors.toList()); + final Value response = host.handleCommand(context.getSource(), customSuggester.function, args); + if (!(response instanceof ListValue)) + { + throw error("Custom suggester should return a list of options" + " for custom type " + suffix); + } + final Collection res = ((ListValue) response).getItems().stream().map(Value::getString).collect(Collectors.toList()); CarpetProfiler.end_current_section(currentSection); return res; } - if (needsMatching) return examples; - //return Lists.newArrayList(""); - // better than nothing I guess - // nothing is such a bad default. - return Collections.singletonList("... "+getTypeSuffix()); + return needsMatching ? examples : Collections.singletonList("... " + getTypeSuffix()); } - protected boolean optionMatchesPrefix(String prefix, String option) + protected boolean optionMatchesPrefix(final String prefix, String option) { if (!caseSensitive) { - //prefix = prefix.toLowerCase(Locale.ROOT); option = option.toLowerCase(Locale.ROOT); } - for(int i = 0; !option.startsWith(prefix, i); ++i) + for (int i = 0; !option.startsWith(prefix, i); ++i) { i = option.indexOf('_', i); - if (i < 0) return false; + if (i < 0) + { + return false; + } } return true; } @@ -445,69 +473,105 @@ public abstract class CommandArgument private static class StringArgument extends CommandArgument { Set validOptions = Collections.emptySet(); + private StringArgument() { super("string", StringArgumentType.StringType.QUOTABLE_PHRASE.getExamples(), true); } @Override - public ArgumentType getArgumentType(CarpetScriptHost host) + public ArgumentType getArgumentType(final CarpetScriptHost host) { return StringArgumentType.string(); } @Override - public Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + public Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { String choseValue = StringArgumentType.getString(context, param); - if (!caseSensitive) choseValue = choseValue.toLowerCase(Locale.ROOT); + if (!caseSensitive) + { + choseValue = choseValue.toLowerCase(Locale.ROOT); + } if (!validOptions.isEmpty() && !validOptions.contains(choseValue)) { - throw new SimpleCommandExceptionType(Component.literal("Incorrect value for "+param+": "+choseValue+" for custom type "+suffix)).create(); + throw new SimpleCommandExceptionType(Component.literal("Incorrect value for " + param + ": " + choseValue + " for custom type " + suffix)).create(); } return StringValue.of(choseValue); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); if (config.containsKey("options")) { - Value optionsValue = config.get("options"); - if (!(optionsValue instanceof ListValue)) throw error("Custom string type requires options passed as a list"+" for custom type "+suffix); + final Value optionsValue = config.get("options"); + if (!(optionsValue instanceof ListValue)) + { + throw error("Custom string type requires options passed as a list" + " for custom type " + suffix); + } validOptions = ((ListValue) optionsValue).getItems().stream() - .map(v -> caseSensitive?v.getString():(v.getString().toLowerCase(Locale.ROOT))) + .map(v -> caseSensitive ? v.getString() : (v.getString().toLowerCase(Locale.ROOT))) .collect(Collectors.toSet()); } } @Override - protected Collection getOptions(CommandContext context, CarpetScriptHost host) throws CommandSyntaxException + protected Collection getOptions(final CommandContext context, final CarpetScriptHost host) throws CommandSyntaxException { - return validOptions.isEmpty()?super.getOptions(context, host):validOptions; + return validOptions.isEmpty() ? super.getOptions(context, host) : validOptions; } @Override - protected Supplier factory(MinecraftServer server) { return StringArgument::new; } + protected Supplier factory(final MinecraftServer server) + { + return StringArgument::new; + } } private static class WordArgument extends StringArgument { - private WordArgument() { super(); suffix = "term"; examples = StringArgumentType.StringType.SINGLE_WORD.getExamples(); } + private WordArgument() + { + super(); + suffix = "term"; + examples = StringArgumentType.StringType.SINGLE_WORD.getExamples(); + } + @Override - public ArgumentType getArgumentType(CarpetScriptHost host) { return StringArgumentType.word(); } + public ArgumentType getArgumentType(final CarpetScriptHost host) + { + return StringArgumentType.word(); + } + @Override - protected Supplier factory(MinecraftServer server) { return WordArgument::new; } + protected Supplier factory(final MinecraftServer server) + { + return WordArgument::new; + } } private static class GreedyStringArgument extends StringArgument { - private GreedyStringArgument() { super();suffix = "text"; examples = StringArgumentType.StringType.GREEDY_PHRASE.getExamples(); } + private GreedyStringArgument() + { + super(); + suffix = "text"; + examples = StringArgumentType.StringType.GREEDY_PHRASE.getExamples(); + } + @Override - public ArgumentType getArgumentType(CarpetScriptHost host) { return StringArgumentType.greedyString(); } + public ArgumentType getArgumentType(final CarpetScriptHost host) + { + return StringArgumentType.greedyString(); + } + @Override - protected Supplier factory(MinecraftServer server) { return GreedyStringArgument::new; } + protected Supplier factory(final MinecraftServer server) + { + return GreedyStringArgument::new; + } } private static class BlockPosArgument extends CommandArgument @@ -520,29 +584,29 @@ public abstract class CommandArgument } @Override - public ArgumentType getArgumentType(CarpetScriptHost host) + public ArgumentType getArgumentType(final CarpetScriptHost host) { return net.minecraft.commands.arguments.coordinates.BlockPosArgument.blockPos(); } @Override - public Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + public Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { - BlockPos pos = mustBeLoaded + final BlockPos pos = mustBeLoaded ? net.minecraft.commands.arguments.coordinates.BlockPosArgument.getLoadedBlockPos(context, param) : net.minecraft.commands.arguments.coordinates.BlockPosArgument.getSpawnablePos(context, param); return ValueConversions.of(pos); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); mustBeLoaded = config.getOrDefault("loaded", Value.FALSE).getBoolean(); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return BlockPosArgument::new; } @@ -557,27 +621,28 @@ public abstract class CommandArgument super("location", Vec3Argument.vec3().getExamples(), false); blockCentered = true; } + @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) + protected ArgumentType getArgumentType(final CarpetScriptHost host) { return Vec3Argument.vec3(blockCentered); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { return ValueConversions.of(Vec3Argument.getVec3(context, param)); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); blockCentered = config.getOrDefault("block_centered", Value.TRUE).getBoolean(); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return LocationArgument::new; } @@ -594,31 +659,38 @@ public abstract class CommandArgument onlyFans = false; single = false; } + @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) + protected ArgumentType getArgumentType(final CarpetScriptHost host) { if (onlyFans) { - return single?net.minecraft.commands.arguments.EntityArgument.player():net.minecraft.commands.arguments.EntityArgument.players(); - } - else - { - return single?net.minecraft.commands.arguments.EntityArgument.entity():net.minecraft.commands.arguments.EntityArgument.entities(); + return single ? net.minecraft.commands.arguments.EntityArgument.player() : net.minecraft.commands.arguments.EntityArgument.players(); } + return single ? net.minecraft.commands.arguments.EntityArgument.entity() : net.minecraft.commands.arguments.EntityArgument.entities(); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { - Collection founds = net.minecraft.commands.arguments.EntityArgument.getOptionalEntities(context, param); - if (!single) return ListValue.wrap(founds.stream().map(EntityValue::new)); - if (founds.size() == 0) return Value.NULL; - if (founds.size() == 1) return new EntityValue(founds.iterator().next()); - throw new SimpleCommandExceptionType(Component.literal("Multiple entities returned while only one was requested"+" for custom type "+suffix)).create(); + final Collection founds = net.minecraft.commands.arguments.EntityArgument.getOptionalEntities(context, param); + if (!single) + { + return ListValue.wrap(founds.stream().map(EntityValue::new)); + } + if (founds.size() == 0) + { + return Value.NULL; + } + if (founds.size() == 1) + { + return new EntityValue(founds.iterator().next()); + } + throw new SimpleCommandExceptionType(Component.literal("Multiple entities returned while only one was requested" + " for custom type " + suffix)).create(); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); onlyFans = config.getOrDefault("players", Value.FALSE).getBoolean(); @@ -626,7 +698,7 @@ public abstract class CommandArgument } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return EntityArgument::new; } @@ -641,32 +713,42 @@ public abstract class CommandArgument super("players", GameProfileArgument.gameProfile().getExamples(), false); single = false; } + @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) + protected ArgumentType getArgumentType(final CarpetScriptHost host) { return GameProfileArgument.gameProfile(); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { - Collection profiles = GameProfileArgument.getGameProfiles(context, param); - if (!single) return ListValue.wrap(profiles.stream().map(p -> StringValue.of(p.getName()))); - int size = profiles.size(); - if (size == 0) return Value.NULL; - if (size == 1) return StringValue.of(profiles.iterator().next().getName()); - throw new SimpleCommandExceptionType(Component.literal("Multiple game profiles returned while only one was requested"+" for custom type "+suffix)).create(); + final Collection profiles = GameProfileArgument.getGameProfiles(context, param); + if (!single) + { + return ListValue.wrap(profiles.stream().map(p -> StringValue.of(p.getName()))); + } + final int size = profiles.size(); + if (size == 0) + { + return Value.NULL; + } + if (size == 1) + { + return StringValue.of(profiles.iterator().next().getName()); + } + throw new SimpleCommandExceptionType(Component.literal("Multiple game profiles returned while only one was requested" + " for custom type " + suffix)).create(); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); single = config.getOrDefault("single", Value.FALSE).getBoolean(); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return PlayerProfileArgument::new; } @@ -682,32 +764,42 @@ public abstract class CommandArgument single = false; suggestionProvider = param -> ScoreHolderArgument.SUGGEST_SCORE_HOLDERS; } + @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) + protected ArgumentType getArgumentType(final CarpetScriptHost host) { - return single?ScoreHolderArgument.scoreHolder():ScoreHolderArgument.scoreHolders(); + return single ? ScoreHolderArgument.scoreHolder() : ScoreHolderArgument.scoreHolders(); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { - Collection holders = ScoreHolderArgument.getNames(context, param); - if (!single) return ListValue.wrap(holders.stream().map(StringValue::of)); - int size = holders.size(); - if (size == 0) return Value.NULL; - if (size == 1) return StringValue.of(holders.iterator().next()); - throw new SimpleCommandExceptionType(Component.literal("Multiple score holders returned while only one was requested"+" for custom type "+suffix)).create(); + final Collection holders = ScoreHolderArgument.getNames(context, param); + if (!single) + { + return ListValue.wrap(holders.stream().map(StringValue::of)); + } + final int size = holders.size(); + if (size == 0) + { + return Value.NULL; + } + if (size == 1) + { + return StringValue.of(holders.iterator().next()); + } + throw new SimpleCommandExceptionType(Component.literal("Multiple score holders returned while only one was requested" + " for custom type " + suffix)).create(); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); single = config.getOrDefault("single", Value.FALSE).getBoolean(); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return PlayerProfileArgument::new; } @@ -716,35 +808,36 @@ public abstract class CommandArgument private static class TagArgument extends CommandArgument { boolean mapRequired; + private TagArgument() { super("tag", CompoundTagArgument.compoundTag().getExamples(), false); mapRequired = true; } + @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) + protected ArgumentType getArgumentType(final CarpetScriptHost host) { - return mapRequired?CompoundTagArgument.compoundTag(): NbtTagArgument.nbtTag(); + return mapRequired ? CompoundTagArgument.compoundTag() : NbtTagArgument.nbtTag(); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { - if (mapRequired) - return new NBTSerializableValue(CompoundTagArgument.getCompoundTag(context, param)); - else - return new NBTSerializableValue(NbtTagArgument.getNbtTag(context, param)); + return mapRequired + ? new NBTSerializableValue(CompoundTagArgument.getCompoundTag(context, param)) + : new NBTSerializableValue(NbtTagArgument.getNbtTag(context, param)); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); mapRequired = !config.getOrDefault("allow_element", Value.FALSE).getBoolean(); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return TagArgument::new; } @@ -760,36 +853,39 @@ public abstract class CommandArgument } @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) + protected ArgumentType getArgumentType(final CarpetScriptHost host) { return ResourceLocationArgument.id(); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { - ResourceLocation choseValue = ResourceLocationArgument.getId(context, param); + final ResourceLocation choseValue = ResourceLocationArgument.getId(context, param); if (!validOptions.isEmpty() && !validOptions.contains(choseValue)) { - throw new SimpleCommandExceptionType(Component.literal("Incorrect value for "+param+": "+choseValue+" for custom type "+suffix)).create(); + throw new SimpleCommandExceptionType(Component.literal("Incorrect value for " + param + ": " + choseValue + " for custom type " + suffix)).create(); } return ValueConversions.of(choseValue); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return CustomIdentifierArgument::new; } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); if (config.containsKey("options")) { - Value optionsValue = config.get("options"); - if (!(optionsValue instanceof ListValue)) throw error("Custom sting type requires options passed as a list"+" for custom type "+suffix); + final Value optionsValue = config.get("options"); + if (!(optionsValue instanceof ListValue)) + { + throw error("Custom sting type requires options passed as a list" + " for custom type " + suffix); + } validOptions = ((ListValue) optionsValue).getItems().stream().map(v -> new ResourceLocation(v.getString())).collect(Collectors.toSet()); } } @@ -799,13 +895,14 @@ public abstract class CommandArgument { private Double min = null; private Double max = null; + private FloatArgument() { super("float", DoubleArgumentType.doubleArg().getExamples(), true); } @Override - public ArgumentType getArgumentType(CarpetScriptHost host) + public ArgumentType getArgumentType(final CarpetScriptHost host) { if (min != null) { @@ -819,13 +916,13 @@ public abstract class CommandArgument } @Override - public Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + public Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { return new NumericValue(DoubleArgumentType.getDouble(context, param)); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); if (config.containsKey("min")) @@ -836,11 +933,14 @@ public abstract class CommandArgument { max = NumericValue.asNumber(config.get("max"), "max").getDouble(); } - if (max != null && min == null) throw error("Double types cannot be only upper-bounded"+" for custom type "+suffix); + if (max != null && min == null) + { + throw error("Double types cannot be only upper-bounded" + " for custom type " + suffix); + } } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return FloatArgument::new; } @@ -850,13 +950,14 @@ public abstract class CommandArgument { private Long min = null; private Long max = null; + private IntArgument() { super("int", LongArgumentType.longArg().getExamples(), true); } @Override - public ArgumentType getArgumentType(CarpetScriptHost host) + public ArgumentType getArgumentType(final CarpetScriptHost host) { if (min != null) { @@ -870,13 +971,13 @@ public abstract class CommandArgument } @Override - public Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + public Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { return new NumericValue(LongArgumentType.getLong(context, param)); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); if (config.containsKey("min")) @@ -887,57 +988,112 @@ public abstract class CommandArgument { max = NumericValue.asNumber(config.get("max"), "max").getLong(); } - if (max != null && min == null) throw error("Double types cannot be only upper-bounded"+" for custom type "+suffix); + if (max != null && min == null) + { + throw error("Double types cannot be only upper-bounded" + " for custom type " + suffix); + } } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return IntArgument::new; } } + private static class SlotArgument extends CommandArgument { - private static record ContainerIds(IntSet numericalIds, Set commandIds) {} + private record ContainerIds(IntSet numericalIds, Set commandIds) + { + } + private String restrict; - private static final Map RESTRICTED_CONTAINERS = new HashMap(){{ + private static final Map RESTRICTED_CONTAINERS = new HashMap<>() + {{ int i; - for (String source : Arrays.asList("player", "enderchest", "equipment", "armor", "weapon", "container", "villager", "horse")) + for (final String source : Arrays.asList("player", "enderchest", "equipment", "armor", "weapon", "container", "villager", "horse")) + { put(source, new ContainerIds(new IntOpenHashSet(), new HashSet<>())); - for (i = 0; i < 41; i++) get("player").numericalIds().add(i); - for(i = 0; i < 41; i++) get("player").commandIds().add("container." + i); - for(i = 0; i < 9; i++) get("player").commandIds().add("hotbar." + i); - for(i = 0; i < 27; i++) get("player").commandIds().add("inventory." + i); - for (String place : Arrays.asList("weapon", "weapon.mainhand", "weapon.offhand")) + } + for (i = 0; i < 41; i++) + { + get("player").numericalIds().add(i); + } + for (i = 0; i < 41; i++) + { + get("player").commandIds().add("container." + i); + } + for (i = 0; i < 9; i++) + { + get("player").commandIds().add("hotbar." + i); + } + for (i = 0; i < 27; i++) + { + get("player").commandIds().add("inventory." + i); + } + for (final String place : Arrays.asList("weapon", "weapon.mainhand", "weapon.offhand")) { get("player").commandIds().add(place); get("equipment").commandIds().add(place); get("weapon").commandIds().add(place); } - for (String place : Arrays.asList("armor.feet","armor.legs", "armor.chest","armor.head")) + for (final String place : Arrays.asList("armor.feet", "armor.legs", "armor.chest", "armor.head")) { get("player").commandIds().add(place); get("equipment").commandIds().add(place); get("armor").commandIds().add(place); } - for (i = 0; i < 27; i++) get("enderchest").numericalIds().add(200+i); - for(i = 0; i < 27; i++) get("enderchest").commandIds().add("enderchest." + i); + for (i = 0; i < 27; i++) + { + get("enderchest").numericalIds().add(200 + i); + } + for (i = 0; i < 27; i++) + { + get("enderchest").commandIds().add("enderchest." + i); + } - for (i = 0; i < 6; i++) get("equipment").numericalIds().add(98+i); + for (i = 0; i < 6; i++) + { + get("equipment").numericalIds().add(98 + i); + } - for (i = 0; i < 4; i++) get("armor").numericalIds().add(100+i); + for (i = 0; i < 4; i++) + { + get("armor").numericalIds().add(100 + i); + } - for (i = 0; i < 2; i++) get("weapon").numericalIds().add(98+i); + for (i = 0; i < 2; i++) + { + get("weapon").numericalIds().add(98 + i); + } - for (i = 0; i < 54; i++) get("container").numericalIds().add(i); - for(i = 0; i < 41; i++) get("container").commandIds().add("container." + i); + for (i = 0; i < 54; i++) + { + get("container").numericalIds().add(i); + } + for (i = 0; i < 41; i++) + { + get("container").commandIds().add("container." + i); + } - for (i = 0; i < 8; i++) get("villager").numericalIds().add(i); - for(i = 0; i < 8; i++) get("villager").commandIds().add("villager." + i); + for (i = 0; i < 8; i++) + { + get("villager").numericalIds().add(i); + } + for (i = 0; i < 8; i++) + { + get("villager").commandIds().add("villager." + i); + } - for (i = 0; i < 15; i++) get("horse").numericalIds().add(500+i); - for(i = 0; i < 15; i++) get("horse").commandIds().add("horse." + i); + for (i = 0; i < 15; i++) + { + get("horse").numericalIds().add(500 + i); + } + for (i = 0; i < 15; i++) + { + get("horse").commandIds().add("horse." + i); + } get("horse").numericalIds().add(400); get("horse").commandIds().add("horse.saddle"); get("horse").numericalIds().add(401); @@ -950,24 +1106,24 @@ public abstract class CommandArgument } @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) throws CommandSyntaxException + protected ArgumentType getArgumentType(final CarpetScriptHost host) throws CommandSyntaxException { return net.minecraft.commands.arguments.SlotArgument.slot(); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { - int slot = net.minecraft.commands.arguments.SlotArgument.getSlot(context, param); + final int slot = net.minecraft.commands.arguments.SlotArgument.getSlot(context, param); if (restrict != null && !RESTRICTED_CONTAINERS.get(restrict).numericalIds().contains(slot)) { - throw new SimpleCommandExceptionType(Component.literal("Incorrect slot restricted to "+restrict+" for custom type "+suffix)).create(); + throw new SimpleCommandExceptionType(Component.literal("Incorrect slot restricted to " + restrict + " for custom type " + suffix)).create(); } return ValueConversions.ofVanillaSlotResult(slot); } @Override - protected void configure(Map config, CarpetScriptHost host) throws CommandSyntaxException + protected void configure(final Map config, final CarpetScriptHost host) throws CommandSyntaxException { super.configure(config, host); if (config.containsKey("restrict")) @@ -975,18 +1131,20 @@ public abstract class CommandArgument restrict = config.get("restrict").getString().toLowerCase(Locale.ROOT); needsMatching = true; if (!RESTRICTED_CONTAINERS.containsKey(restrict)) - throw error("Incorrect slot restriction "+restrict+" for custom type "+suffix); + { + throw error("Incorrect slot restriction " + restrict + " for custom type " + suffix); + } } } @Override - protected Collection getOptions(CommandContext context, CarpetScriptHost host) throws CommandSyntaxException + protected Collection getOptions(final CommandContext context, final CarpetScriptHost host) throws CommandSyntaxException { - return restrict==null?super.getOptions(context, host):RESTRICTED_CONTAINERS.get(restrict).commandIds(); + return restrict == null ? super.getOptions(context, host) : RESTRICTED_CONTAINERS.get(restrict).commandIds(); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { return SlotArgument::new; } @@ -1010,7 +1168,7 @@ public abstract class CommandArgument ArgumentType get(CommandBuildContext regAccess) throws CommandSyntaxException; } - public static class VanillaUnconfigurableArgument extends CommandArgument + public static class VanillaUnconfigurableArgument extends CommandArgument { private final ArgumentProvider argumentTypeSupplier; private final ArgumentProviderEx argumentTypeSupplierEx; @@ -1018,18 +1176,18 @@ public abstract class CommandArgument private final boolean providesExamples; public VanillaUnconfigurableArgument( - String suffix, - ArgumentProvider argumentTypeSupplier, - ValueExtractor valueExtractor, - boolean suggestFromExamples - ) + final String suffix, + final ArgumentProvider argumentTypeSupplier, + final ValueExtractor valueExtractor, + final boolean suggestFromExamples + ) { super(suffix, null, suggestFromExamples); try { this.examples = argumentTypeSupplier.get().getExamples(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { this.examples = Collections.emptyList(); } @@ -1038,11 +1196,12 @@ public abstract class CommandArgument this.valueExtractor = valueExtractor; this.argumentTypeSupplierEx = null; } + public VanillaUnconfigurableArgument( - String suffix, - ArgumentProvider argumentTypeSupplier, - ValueExtractor valueExtractor, - SuggestionProvider suggester + final String suffix, + final ArgumentProvider argumentTypeSupplier, + final ValueExtractor valueExtractor, + final SuggestionProvider suggester ) { super(suffix, Collections.emptyList(), false); @@ -1052,12 +1211,13 @@ public abstract class CommandArgument this.valueExtractor = valueExtractor; this.argumentTypeSupplierEx = null; } + public VanillaUnconfigurableArgument( - String suffix, - ArgumentProviderEx argumentTypeSupplier, - ValueExtractor valueExtractor, - boolean suggestFromExamples, - MinecraftServer server) + final String suffix, + final ArgumentProviderEx argumentTypeSupplier, + final ValueExtractor valueExtractor, + final boolean suggestFromExamples, + final MinecraftServer server) { super(suffix, null, suggestFromExamples); try @@ -1065,7 +1225,7 @@ public abstract class CommandArgument final CommandBuildContext context = CommandBuildContext.simple(server.registryAccess(), server.getWorldData().enabledFeatures()); this.examples = argumentTypeSupplier.get(context).getExamples(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { this.examples = Collections.emptyList(); } @@ -1076,10 +1236,10 @@ public abstract class CommandArgument } public VanillaUnconfigurableArgument( - String suffix, - ArgumentProviderEx argumentTypeSupplier, - ValueExtractor valueExtractor, - SuggestionProvider suggester + final String suffix, + final ArgumentProviderEx argumentTypeSupplier, + final ValueExtractor valueExtractor, + final SuggestionProvider suggester ) { super(suffix, Collections.emptyList(), false); @@ -1091,10 +1251,10 @@ public abstract class CommandArgument } public VanillaUnconfigurableArgument( - String suffix, - ArgumentProviderEx argumentTypeSupplier, - ValueExtractor valueExtractor, - Function> suggesterGen + final String suffix, + final ArgumentProviderEx argumentTypeSupplier, + final ValueExtractor valueExtractor, + final Function> suggesterGen ) { super(suffix, Collections.emptyList(), false); @@ -1106,8 +1266,8 @@ public abstract class CommandArgument } public VanillaUnconfigurableArgument( - String suffix, - ResourceKey> registry + final String suffix, + final ResourceKey> registry ) { this( @@ -1119,24 +1279,25 @@ public abstract class CommandArgument } @Override - protected ArgumentType getArgumentType(CarpetScriptHost host) throws CommandSyntaxException + protected ArgumentType getArgumentType(final CarpetScriptHost host) throws CommandSyntaxException { - if (argumentTypeSupplier != null) return argumentTypeSupplier.get(); - CommandBuildContext registryAccess = CommandBuildContext.simple(host.scriptServer().server.registryAccess(), host.scriptServer().server.getWorldData().enabledFeatures()); - return argumentTypeSupplierEx.get(registryAccess); + return argumentTypeSupplier != null + ? argumentTypeSupplier.get() + : argumentTypeSupplierEx.get(CommandBuildContext.simple(host.scriptServer().server.registryAccess(), host.scriptServer().server.getWorldData().enabledFeatures())); } @Override - protected Value getValueFromContext(CommandContext context, String param) throws CommandSyntaxException + protected Value getValueFromContext(final CommandContext context, final String param) throws CommandSyntaxException { return valueExtractor.apply(context, param); } @Override - protected Supplier factory(MinecraftServer server) + protected Supplier factory(final MinecraftServer server) { - if (argumentTypeSupplier != null) return () -> new VanillaUnconfigurableArgument(getTypeSuffix(), argumentTypeSupplier, valueExtractor, providesExamples); - return () -> new VanillaUnconfigurableArgument(getTypeSuffix(), argumentTypeSupplierEx, valueExtractor, providesExamples, server); + return argumentTypeSupplier != null + ? (() -> new VanillaUnconfigurableArgument(getTypeSuffix(), argumentTypeSupplier, valueExtractor, providesExamples)) + : (() -> new VanillaUnconfigurableArgument(getTypeSuffix(), argumentTypeSupplierEx, valueExtractor, providesExamples, server)); } } } diff --git a/src/main/java/carpet/script/command/CommandToken.java b/src/main/java/carpet/script/command/CommandToken.java index 257ac8c2..7f028ee9 100644 --- a/src/main/java/carpet/script/command/CommandToken.java +++ b/src/main/java/carpet/script/command/CommandToken.java @@ -5,11 +5,13 @@ import carpet.script.value.FunctionValue; import com.google.common.collect.Lists; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; + import net.minecraft.commands.CommandSourceStack; import static net.minecraft.commands.Commands.literal; @@ -20,41 +22,46 @@ public class CommandToken implements Comparable public boolean isArgument; public CommandArgument type; - private CommandToken(String surface, CommandArgument type ) + private CommandToken(final String surface, final CommandArgument type) { this.surface = surface; this.type = type; isArgument = type != null; } - public static CommandToken getToken(String source, CarpetScriptHost host) + public static CommandToken getToken(String source, final CarpetScriptHost host) { // todo add more type checking and return null if (!source.startsWith("<")) { - if (!source.matches("[_a-zA-Z]+")) return null; - return new CommandToken(source, null); + return source.matches("[_a-zA-Z]+") ? new CommandToken(source, null) : null; } - source = source.substring(1, source.length()-1); - if (!source.matches("[_a-zA-Z]+")) return null; - CommandArgument arg = CommandArgument.getTypeForArgument(source, host); - return new CommandToken(source, arg); + source = source.substring(1, source.length() - 1); + return source.matches("[_a-zA-Z]+") ? new CommandToken(source, CommandArgument.getTypeForArgument(source, host)) : null; } - public static List parseSpec(String spec, CarpetScriptHost host) throws CommandSyntaxException + public static List parseSpec(String spec, final CarpetScriptHost host) throws CommandSyntaxException { spec = spec.trim(); - if (spec.isEmpty()) return Collections.emptyList(); - List elements = new ArrayList<>(); - HashSet seenArgs = new HashSet<>(); - for (String el: spec.split("\\s+")) + if (spec.isEmpty()) { - CommandToken tok = CommandToken.getToken(el, host); - if (tok == null) throw CommandArgument.error("Unrecognized command token: "+ el); + return Collections.emptyList(); + } + final List elements = new ArrayList<>(); + final HashSet seenArgs = new HashSet<>(); + for (final String el : spec.split("\\s+")) + { + final CommandToken tok = CommandToken.getToken(el, host); + if (tok == null) + { + throw CommandArgument.error("Unrecognized command token: " + el); + } if (tok.isArgument) { if (seenArgs.contains(tok.surface)) - throw CommandArgument.error("Repeated command argument: "+tok.surface+", for '"+spec+"'. Argument names have to be unique"); + { + throw CommandArgument.error("Repeated command argument: " + tok.surface + ", for '" + spec + "'. Argument names have to be unique"); + } seenArgs.add(tok.surface); } elements.add(tok); @@ -62,28 +69,33 @@ public class CommandToken implements Comparable return elements; } - public static String specFromSignature(FunctionValue function) + public static String specFromSignature(final FunctionValue function) { - List tokens = Lists.newArrayList(function.getString()); - for (String arg : function.getArguments()) tokens.add("<"+arg+">"); + final List tokens = Lists.newArrayList(function.getString()); + for (final String arg : function.getArguments()) + { + tokens.add("<" + arg + ">"); + } return String.join(" ", tokens); } - - public ArgumentBuilder getCommandNode(CarpetScriptHost host) throws CommandSyntaxException + public ArgumentBuilder getCommandNode(final CarpetScriptHost host) throws CommandSyntaxException { - if (isArgument) - return CommandArgument.argumentNode(surface, host); - return literal(surface); - + return isArgument ? CommandArgument.argumentNode(surface, host) : literal(surface); } @Override - public boolean equals(Object o) + public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CommandToken that = (CommandToken) o; + if (this == o) + { + return true; + } + if (o == null || getClass() != o.getClass()) + { + return false; + } + final CommandToken that = (CommandToken) o; return surface.equals(that.surface) && Objects.equals(type, that.type); } @@ -95,10 +107,16 @@ public class CommandToken implements Comparable } @Override - public int compareTo(CommandToken o) + public int compareTo(final CommandToken o) { - if (isArgument && !o.isArgument) return 1; - if (!isArgument && o.isArgument) return -1; + if (isArgument && !o.isArgument) + { + return 1; + } + if (!isArgument && o.isArgument) + { + return -1; + } return surface.compareTo(o.surface); } } diff --git a/src/main/java/carpet/script/exception/BreakStatement.java b/src/main/java/carpet/script/exception/BreakStatement.java index 8705d124..76c69a7a 100644 --- a/src/main/java/carpet/script/exception/BreakStatement.java +++ b/src/main/java/carpet/script/exception/BreakStatement.java @@ -4,7 +4,7 @@ import carpet.script.value.Value; public class BreakStatement extends ExitStatement { - public BreakStatement(Value value) + public BreakStatement(final Value value) { super(value); } diff --git a/src/main/java/carpet/script/exception/CarpetExpressionException.java b/src/main/java/carpet/script/exception/CarpetExpressionException.java index 849e99ad..4ca5d115 100644 --- a/src/main/java/carpet/script/exception/CarpetExpressionException.java +++ b/src/main/java/carpet/script/exception/CarpetExpressionException.java @@ -2,25 +2,28 @@ package carpet.script.exception; import carpet.script.value.FunctionValue; import carpet.utils.Messenger; + import java.util.List; + import net.minecraft.commands.CommandSourceStack; public class CarpetExpressionException extends StacklessRuntimeException implements ResolvedException { public final List stack; - public CarpetExpressionException(String message, List stack) + public CarpetExpressionException(final String message, final List stack) { super(message); this.stack = stack; } - public void printStack(CommandSourceStack source) + + public void printStack(final CommandSourceStack source) { if (stack != null && !stack.isEmpty()) { - for (FunctionValue fun : stack) + for (final FunctionValue fun : stack) { - Messenger.m(source, "e ... in "+fun.fullName(), "e /"+(fun.getToken().lineno+1)+":"+(fun.getToken().linepos+1)); + Messenger.m(source, "e ... in " + fun.fullName(), "e /" + (fun.getToken().lineno + 1) + ":" + (fun.getToken().linepos + 1)); } } } diff --git a/src/main/java/carpet/script/exception/ContinueStatement.java b/src/main/java/carpet/script/exception/ContinueStatement.java index f31c5af3..a471d4f4 100644 --- a/src/main/java/carpet/script/exception/ContinueStatement.java +++ b/src/main/java/carpet/script/exception/ContinueStatement.java @@ -4,7 +4,7 @@ import carpet.script.value.Value; public class ContinueStatement extends ExitStatement { - public ContinueStatement(Value value) + public ContinueStatement(final Value value) { super(value); } diff --git a/src/main/java/carpet/script/exception/ExitStatement.java b/src/main/java/carpet/script/exception/ExitStatement.java index eb258d6f..744ec9f6 100644 --- a/src/main/java/carpet/script/exception/ExitStatement.java +++ b/src/main/java/carpet/script/exception/ExitStatement.java @@ -6,7 +6,8 @@ import carpet.script.value.Value; public class ExitStatement extends StacklessRuntimeException { public final Value retval; - public ExitStatement(Value value) + + public ExitStatement(final Value value) { retval = value; } diff --git a/src/main/java/carpet/script/exception/ExpressionException.java b/src/main/java/carpet/script/exception/ExpressionException.java index 64d97af2..71048589 100644 --- a/src/main/java/carpet/script/exception/ExpressionException.java +++ b/src/main/java/carpet/script/exception/ExpressionException.java @@ -19,20 +19,23 @@ public class ExpressionException extends StacklessRuntimeException implements Re public final List stack = new ArrayList<>(); private final Supplier lazyMessage; private String cachedMessage = null; - public static void prepareForDoom(){ + + public static void prepareForDoom() + { Messenger.c("foo bar"); } - public ExpressionException(Context c, Expression e, String message) + public ExpressionException(final Context c, final Expression e, final String message) { this(c, e, Tokenizer.Token.NONE, message); } - public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message) + public ExpressionException(final Context c, final Expression e, final Tokenizer.Token t, final String message) { this(c, e, t, message, Collections.emptyList()); } - public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message, List stack) + + public ExpressionException(final Context c, final Expression e, final Tokenizer.Token t, final String message, final List stack) { super("Error"); this.stack.addAll(stack); @@ -41,7 +44,7 @@ public class ExpressionException extends StacklessRuntimeException implements Re context = c; } - public ExpressionException(Context c, Expression e, Tokenizer.Token t, Supplier messageSupplier, List stack) + public ExpressionException(final Context c, final Expression e, final Tokenizer.Token t, final Supplier messageSupplier, final List stack) { super("Error"); this.stack.addAll(stack); @@ -50,13 +53,13 @@ public class ExpressionException extends StacklessRuntimeException implements Re context = c; } - private static List makeError(Expression expr, /*Nullable*/Tokenizer.Token token, String errmessage) + private static List makeError(final Expression expr, /*Nullable*/final Tokenizer.Token token, String errmessage) { - List errMsg = new ArrayList<>(); - errmessage += expr.getModuleName() == null?"":(" in "+expr.getModuleName()); + final List errMsg = new ArrayList<>(); + errmessage += expr.getModuleName() == null ? "" : (" in " + expr.getModuleName()); if (token != null) { - List snippet = expr.getExpressionSnippet(token); + final List snippet = expr.getExpressionSnippet(token); errMsg.addAll(snippet); if (snippet.size() != 1) @@ -72,11 +75,11 @@ public class ExpressionException extends StacklessRuntimeException implements Re return errMsg; } - synchronized static String makeMessage(Context c, Expression e, Tokenizer.Token t, String message) throws ExpressionException + static synchronized String makeMessage(final Context c, final Expression e, final Tokenizer.Token t, final String message) throws ExpressionException { if (c.getErrorSnooper() != null) { - List alternative = c.getErrorSnooper().apply(e, t, c, message); + final List alternative = c.getErrorSnooper().apply(e, t, c, message); if (alternative != null) { return String.join("\n", alternative); @@ -84,12 +87,13 @@ public class ExpressionException extends StacklessRuntimeException implements Re } return String.join("\n", makeError(e, t, message)); } - + @Override - public String getMessage() { + public String getMessage() + { if (cachedMessage == null) { - cachedMessage = lazyMessage.get(); + cachedMessage = lazyMessage.get(); } return cachedMessage; } diff --git a/src/main/java/carpet/script/exception/IntegrityException.java b/src/main/java/carpet/script/exception/IntegrityException.java index 262c57f9..7aee600b 100644 --- a/src/main/java/carpet/script/exception/IntegrityException.java +++ b/src/main/java/carpet/script/exception/IntegrityException.java @@ -2,7 +2,7 @@ package carpet.script.exception; public class IntegrityException extends RuntimeException { - public IntegrityException(String message) + public IntegrityException(final String message) { super(message); } diff --git a/src/main/java/carpet/script/exception/InternalExpressionException.java b/src/main/java/carpet/script/exception/InternalExpressionException.java index 8706f710..dec1b9c5 100644 --- a/src/main/java/carpet/script/exception/InternalExpressionException.java +++ b/src/main/java/carpet/script/exception/InternalExpressionException.java @@ -12,23 +12,25 @@ import java.util.List; public class InternalExpressionException extends StacklessRuntimeException { public List stack = new ArrayList<>(); - public InternalExpressionException(String message) + + public InternalExpressionException(final String message) { super(message); } - + /** *

Promotes this simple exception into one with context and extra information. - * + * *

Provides a cleaner way of handling similar exceptions, in this case - * {@link InternalExpressionException} and {@link ThrowStatement} - * @param c Context - * @param e Expression + * {@link InternalExpressionException} and {@link ThrowStatement} + * + * @param c Context + * @param e Expression * @param token Token * @return The new {@link ExpressionException} (or {@link ProcessedThrowStatement}), - * depending on the implementation. + * depending on the implementation. */ - public ExpressionException promote(Context c, Expression e, Tokenizer.Token token) + public ExpressionException promote(final Context c, final Expression e, final Tokenizer.Token token) { return new ExpressionException(c, e, token, getMessage(), stack); } diff --git a/src/main/java/carpet/script/exception/LoadException.java b/src/main/java/carpet/script/exception/LoadException.java index 740a04b1..bdbd4149 100644 --- a/src/main/java/carpet/script/exception/LoadException.java +++ b/src/main/java/carpet/script/exception/LoadException.java @@ -2,18 +2,18 @@ package carpet.script.exception; /** * A Scarpet exception that indicates that load of the app has failed. - * + *

* Goes up the stack to the point of app load and gets caught there, preventing the app from loading with * the given message. - * */ -public class LoadException extends RuntimeException implements ResolvedException { - - public LoadException() { +public class LoadException extends RuntimeException implements ResolvedException +{ + public LoadException() + { super(); } - - public LoadException(String message) { + public LoadException(final String message) + { super(message); } } diff --git a/src/main/java/carpet/script/exception/ProcessedThrowStatement.java b/src/main/java/carpet/script/exception/ProcessedThrowStatement.java index 977cf51f..45c990be 100644 --- a/src/main/java/carpet/script/exception/ProcessedThrowStatement.java +++ b/src/main/java/carpet/script/exception/ProcessedThrowStatement.java @@ -8,12 +8,14 @@ import carpet.script.Tokenizer.Token; import carpet.script.value.FunctionValue; import carpet.script.value.Value; -public class ProcessedThrowStatement extends ExpressionException { +public class ProcessedThrowStatement extends ExpressionException +{ public final Throwables thrownExceptionType; public final Value data; - - public ProcessedThrowStatement(Context c, Expression e, Token token, List stack, Throwables thrownExceptionType, Value data) { - super(c, e, token, () -> "Unhandled "+thrownExceptionType.getId()+" exception: "+data.getString(), stack); + + public ProcessedThrowStatement(final Context c, final Expression e, final Token token, final List stack, final Throwables thrownExceptionType, final Value data) + { + super(c, e, token, () -> "Unhandled " + thrownExceptionType.getId() + " exception: " + data.getString(), stack); this.thrownExceptionType = thrownExceptionType; this.data = data; } diff --git a/src/main/java/carpet/script/exception/ReturnStatement.java b/src/main/java/carpet/script/exception/ReturnStatement.java index b2124d56..e275efb9 100644 --- a/src/main/java/carpet/script/exception/ReturnStatement.java +++ b/src/main/java/carpet/script/exception/ReturnStatement.java @@ -4,8 +4,7 @@ import carpet.script.value.Value; public class ReturnStatement extends ExitStatement { - - public ReturnStatement(Value value) + public ReturnStatement(final Value value) { super(value); } diff --git a/src/main/java/carpet/script/exception/StacklessRuntimeException.java b/src/main/java/carpet/script/exception/StacklessRuntimeException.java index e200d065..5f0f473e 100644 --- a/src/main/java/carpet/script/exception/StacklessRuntimeException.java +++ b/src/main/java/carpet/script/exception/StacklessRuntimeException.java @@ -3,17 +3,21 @@ package carpet.script.exception; /** * A type of {@link RuntimeException} that doesn't spend time producing and filling a stacktrace */ -abstract class StacklessRuntimeException extends RuntimeException { - public StacklessRuntimeException() { +abstract class StacklessRuntimeException extends RuntimeException +{ + public StacklessRuntimeException() + { super(); } - public StacklessRuntimeException(String message) { + public StacklessRuntimeException(final String message) + { super(message); } @Override - public Throwable fillInStackTrace() { + public Throwable fillInStackTrace() + { return this; } } diff --git a/src/main/java/carpet/script/exception/ThrowStatement.java b/src/main/java/carpet/script/exception/ThrowStatement.java index c61470cb..f413246d 100644 --- a/src/main/java/carpet/script/exception/ThrowStatement.java +++ b/src/main/java/carpet/script/exception/ThrowStatement.java @@ -10,21 +10,22 @@ public class ThrowStatement extends InternalExpressionException { private final Throwables type; private final Value data; - + /** * Creates a throw exception from a value, and assigns it a specified message. *

To be used when throwing from Scarpet's {@code throw} function + * * @param data The value to pass * @param type Exception type */ - public ThrowStatement(Value data, Throwables type) + public ThrowStatement(final Value data, final Throwables type) { super(type.getId()); this.data = data; this.type = type; } - public ThrowStatement(Value data, Throwables parent, String subtype) + public ThrowStatement(final Value data, final Throwables parent, final String subtype) { super(subtype); this.data = data; @@ -35,20 +36,22 @@ public class ThrowStatement extends InternalExpressionException * Creates a throw exception.
* Conveniently creates a value from the {@code value} String * to be used easily in Java code + * * @param message The message to display when not handled - * @param type An {@link Throwables} containing the inheritance data - * for this exception. When throwing from Java, - * those exceptions should be pre-registered. + * @param type An {@link Throwables} containing the inheritance data + * for this exception. When throwing from Java, + * those exceptions should be pre-registered. */ - public ThrowStatement(String message, Throwables type) + public ThrowStatement(final String message, final Throwables type) { super(type.getId()); this.data = StringValue.of(message); this.type = type; } - + @Override - public ExpressionException promote(Context c, Expression e, Token token) { + public ExpressionException promote(final Context c, final Expression e, final Token token) + { return new ProcessedThrowStatement(c, e, token, stack, type, data); } } diff --git a/src/main/java/carpet/script/exception/Throwables.java b/src/main/java/carpet/script/exception/Throwables.java index a0a85cb1..48e3d278 100644 --- a/src/main/java/carpet/script/exception/Throwables.java +++ b/src/main/java/carpet/script/exception/Throwables.java @@ -7,41 +7,43 @@ import java.util.Map; * This class contains default Scarpet catchable types, as well as their inheritance and * methods to check whether filters are compatible with those. */ -public class Throwables { +public class Throwables +{ private final String id; private final Throwables parent; private static final Map byId = new HashMap<>(); public static final Throwables THROWN_EXCEPTION_TYPE = register("exception", null); - public static final Throwables VALUE_EXCEPTION = register("value_exception", THROWN_EXCEPTION_TYPE); - public static final Throwables UNKNOWN_ITEM = register("unknown_item", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_BLOCK = register("unknown_block", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_BIOME = register("unknown_biome", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_SOUND = register("unknown_sound", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_PARTICLE = register("unknown_particle", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_POI = register("unknown_poi", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_DIMENSION = register("unknown_dimension", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_STRUCTURE = register("unknown_structure", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_CRITERION = register("unknown_criterion", VALUE_EXCEPTION); - public static final Throwables UNKNOWN_SCREEN = register("unknown_screen", VALUE_EXCEPTION); - public static final Throwables IO_EXCEPTION = register("io_exception", THROWN_EXCEPTION_TYPE); - public static final Throwables NBT_ERROR = register("nbt_error", IO_EXCEPTION); - public static final Throwables JSON_ERROR = register("json_error", IO_EXCEPTION); - public static final Throwables B64_ERROR = register("b64_error", IO_EXCEPTION); - public static final Throwables USER_DEFINED = register("user_exception", THROWN_EXCEPTION_TYPE); + public static final Throwables VALUE_EXCEPTION = register("value_exception", THROWN_EXCEPTION_TYPE); + public static final Throwables UNKNOWN_ITEM = register("unknown_item", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_BLOCK = register("unknown_block", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_BIOME = register("unknown_biome", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_SOUND = register("unknown_sound", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_PARTICLE = register("unknown_particle", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_POI = register("unknown_poi", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_DIMENSION = register("unknown_dimension", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_STRUCTURE = register("unknown_structure", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_CRITERION = register("unknown_criterion", VALUE_EXCEPTION); + public static final Throwables UNKNOWN_SCREEN = register("unknown_screen", VALUE_EXCEPTION); + public static final Throwables IO_EXCEPTION = register("io_exception", THROWN_EXCEPTION_TYPE); + public static final Throwables NBT_ERROR = register("nbt_error", IO_EXCEPTION); + public static final Throwables JSON_ERROR = register("json_error", IO_EXCEPTION); + public static final Throwables B64_ERROR = register("b64_error", IO_EXCEPTION); + public static final Throwables USER_DEFINED = register("user_exception", THROWN_EXCEPTION_TYPE); /** * Creates an exception and registers it to be used as parent for * user defined exceptions in Scarpet's throw function. *

Scarpet exceptions should have a top-level parent being {@link Throwables#THROWN_EXCEPTION_TYPE} - * @param id The value for the exception as a {@link String}. + * + * @param id The value for the exception as a {@link String}. * @param parent The parent of the exception being created, or null if top-level * @return The created exception */ - public static Throwables register(String id, Throwables parent) + public static Throwables register(final String id, final Throwables parent) { - Throwables exc = new Throwables(id, parent); + final Throwables exc = new Throwables(id, parent); byId.put(id, exc); return exc; } @@ -50,28 +52,33 @@ public class Throwables { * Creates a new exception. *

Not suitable for creating exceptions that can't be caught. * Use an {@link InternalExpressionException} for that + * * @param id The exception's value as a {@link String} */ - public Throwables(String id, Throwables parent) + public Throwables(final String id, final Throwables parent) { this.id = id; this.parent = parent; } - public static Throwables getTypeForException(String type) + public static Throwables getTypeForException(final String type) { - Throwables properType = byId.get(type); - if (properType == null) throw new InternalExpressionException("Unknown exception type: "+type); + final Throwables properType = byId.get(type); + if (properType == null) + { + throw new InternalExpressionException("Unknown exception type: " + type); + } return properType; } /** * Checks whether the given filter matches an instance of this exception, by checking equality * with itself and possible parents. + * * @param filter The type to check against * @return Whether or not the given value matches this exception's hierarchy */ - public boolean isRelevantFor(String filter) + public boolean isRelevantFor(final String filter) { return (id.equals(filter) || (parent != null && parent.isRelevantFor(filter))); } @@ -83,9 +90,11 @@ public class Throwables { /** * Returns the throwable type + * * @return The type of this exception */ - public String getId() { + public String getId() + { return id; } } diff --git a/src/main/java/carpet/script/language/Arithmetic.java b/src/main/java/carpet/script/language/Arithmetic.java index c664db8c..4b9c3df5 100644 --- a/src/main/java/carpet/script/language/Arithmetic.java +++ b/src/main/java/carpet/script/language/Arithmetic.java @@ -8,16 +8,17 @@ import carpet.script.value.ListValue; import carpet.script.value.NumericValue; import carpet.script.value.Value; -public class Arithmetic { +public class Arithmetic +{ public static final Value PI = new NumericValue(Math.PI); public static final Value euler = new NumericValue(Math.E); - public static void apply(Expression expression) + public static void apply(final Expression expression) { - expression.addTypedContextFunction("not", 1, Context.Type.BOOLEAN, (c, t, lv) -> BooleanValue.of(lv.get(0).getBoolean()) ); + expression.addTypedContextFunction("not", 1, Context.Type.BOOLEAN, (c, t, lv) -> BooleanValue.of(lv.get(0).getBoolean())); expression.addUnaryFunction("fact", (v) -> { - long number = NumericValue.asNumber(v).getLong(); + final long number = NumericValue.asNumber(v).getLong(); if (number < 21) { long factorial = 1; @@ -40,72 +41,81 @@ public class Arithmetic { return new NumericValue(factorial); }); - expression.addMathematicalUnaryFunction("sin", (d) -> Math.sin(Math.toRadians(d))); - expression.addMathematicalUnaryFunction("cos", (d) -> Math.cos(Math.toRadians(d))); - expression.addMathematicalUnaryFunction("tan", (d) -> Math.tan(Math.toRadians(d))); - expression.addMathematicalUnaryFunction("asin", (d) -> Math.toDegrees(Math.asin(d))); - expression.addMathematicalUnaryFunction("acos", (d) -> Math.toDegrees(Math.acos(d))); - expression.addMathematicalUnaryFunction("atan", (d) -> Math.toDegrees(Math.atan(d))); - expression.addMathematicalBinaryFunction("atan2", (d, d2) -> Math.toDegrees(Math.atan2(d, d2)) ); - expression.addMathematicalUnaryFunction("sinh", Math::sinh ); - expression.addMathematicalUnaryFunction("cosh", Math::cosh ); - expression.addMathematicalUnaryFunction("tanh", Math::tanh ); - expression.addMathematicalUnaryFunction("sec", (d) -> 1.0 / Math.cos(Math.toRadians(d)) ); // Formula: sec(x) = 1 / cos(x) - expression.addMathematicalUnaryFunction("csc", (d) -> 1.0 / Math.sin(Math.toRadians(d)) ); // Formula: csc(x) = 1 / sin(x) - expression.addMathematicalUnaryFunction("sech", (d) -> 1.0 / Math.cosh(d) ); // Formula: sech(x) = 1 / cosh(x) - expression.addMathematicalUnaryFunction("csch", (d) -> 1.0 / Math.sinh(d) ); // Formula: csch(x) = 1 / sinh(x) - expression.addMathematicalUnaryFunction("cot", (d) -> 1.0 / Math.tan(Math.toRadians(d)) ); // Formula: cot(x) = cos(x) / sin(x) = 1 / tan(x) - expression.addMathematicalUnaryFunction("acot", (d) -> Math.toDegrees(Math.atan(1.0 / d)) );// Formula: acot(x) = atan(1/x) - expression.addMathematicalUnaryFunction("coth", (d) -> 1.0 / Math.tanh(d) ); // Formula: coth(x) = 1 / tanh(x) - expression.addMathematicalUnaryFunction("asinh", (d) -> Math.log(d + (Math.sqrt(Math.pow(d, 2) + 1)))); // Formula: asinh(x) = ln(x + sqrt(x^2 + 1)) - expression.addMathematicalUnaryFunction("acosh", (d) -> Math.log(d + (Math.sqrt(Math.pow(d, 2) - 1)))); // Formula: acosh(x) = ln(x + sqrt(x^2 - 1)) - expression.addMathematicalUnaryFunction("atanh", (d) -> // Formula: atanh(x) = 0.5*ln((1 + x)/(1 - x)) + expression.addMathematicalUnaryFunction("sin", d -> Math.sin(Math.toRadians(d))); + expression.addMathematicalUnaryFunction("cos", d -> Math.cos(Math.toRadians(d))); + expression.addMathematicalUnaryFunction("tan", d -> Math.tan(Math.toRadians(d))); + expression.addMathematicalUnaryFunction("asin", d -> Math.toDegrees(Math.asin(d))); + expression.addMathematicalUnaryFunction("acos", d -> Math.toDegrees(Math.acos(d))); + expression.addMathematicalUnaryFunction("atan", d -> Math.toDegrees(Math.atan(d))); + expression.addMathematicalBinaryFunction("atan2", (d, d2) -> Math.toDegrees(Math.atan2(d, d2))); + expression.addMathematicalUnaryFunction("sinh", Math::sinh); + expression.addMathematicalUnaryFunction("cosh", Math::cosh); + expression.addMathematicalUnaryFunction("tanh", Math::tanh); + expression.addMathematicalUnaryFunction("sec", d -> 1.0 / Math.cos(Math.toRadians(d))); // Formula: sec(x) = 1 / cos(x) + expression.addMathematicalUnaryFunction("csc", d -> 1.0 / Math.sin(Math.toRadians(d))); // Formula: csc(x) = 1 / sin(x) + expression.addMathematicalUnaryFunction("sech", d -> 1.0 / Math.cosh(d)); // Formula: sech(x) = 1 / cosh(x) + expression.addMathematicalUnaryFunction("csch", d -> 1.0 / Math.sinh(d)); // Formula: csch(x) = 1 / sinh(x) + expression.addMathematicalUnaryFunction("cot", d -> 1.0 / Math.tan(Math.toRadians(d))); // Formula: cot(x) = cos(x) / sin(x) = 1 / tan(x) + expression.addMathematicalUnaryFunction("acot", d -> Math.toDegrees(Math.atan(1.0 / d)));// Formula: acot(x) = atan(1/x) + expression.addMathematicalUnaryFunction("coth", d -> 1.0 / Math.tanh(d)); // Formula: coth(x) = 1 / tanh(x) + expression.addMathematicalUnaryFunction("asinh", d -> Math.log(d + (Math.sqrt(Math.pow(d, 2) + 1)))); // Formula: asinh(x) = ln(x + sqrt(x^2 + 1)) + expression.addMathematicalUnaryFunction("acosh", d -> Math.log(d + (Math.sqrt(Math.pow(d, 2) - 1)))); // Formula: acosh(x) = ln(x + sqrt(x^2 - 1)) + expression.addMathematicalUnaryFunction("atanh", d -> // Formula: atanh(x) = 0.5*ln((1 + x)/(1 - x)) { if (Math.abs(d) > 1 || Math.abs(d) == 1) + { throw new InternalExpressionException("Number must be |x| < 1"); + } return 0.5 * Math.log((1 + d) / (1 - d)); }); - expression.addMathematicalUnaryFunction("rad", Math::toRadians); + expression.addMathematicalUnaryFunction("rad", Math::toRadians); expression.addMathematicalUnaryFunction("deg", Math::toDegrees); expression.addMathematicalUnaryFunction("ln", Math::log); expression.addMathematicalUnaryFunction("ln1p", Math::log1p); expression.addMathematicalUnaryFunction("log10", Math::log10); - expression.addMathematicalUnaryFunction("log", a -> Math.log(a)/Math.log(2)); - expression.addMathematicalUnaryFunction("log1p", x -> Math.log1p(x)/Math.log(2)); + expression.addMathematicalUnaryFunction("log", a -> Math.log(a) / Math.log(2)); + expression.addMathematicalUnaryFunction("log1p", x -> Math.log1p(x) / Math.log(2)); expression.addMathematicalUnaryFunction("sqrt", Math::sqrt); expression.addMathematicalUnaryFunction("abs", Math::abs); expression.addMathematicalUnaryIntFunction("round", Math::round); - expression.addMathematicalUnaryIntFunction("floor", n -> (long)Math.floor(n)); - expression.addMathematicalUnaryIntFunction("ceil", n -> (long)Math.ceil(n)); + expression.addMathematicalUnaryIntFunction("floor", n -> (long) Math.floor(n)); + expression.addMathematicalUnaryIntFunction("ceil", n -> (long) Math.ceil(n)); expression.addContextFunction("mandelbrot", 3, (c, t, lv) -> { - double a0 = NumericValue.asNumber(lv.get(0)).getDouble(); - double b0 = NumericValue.asNumber(lv.get(1)).getDouble(); - long maxiter = NumericValue.asNumber(lv.get(2)).getLong(); + final double a0 = NumericValue.asNumber(lv.get(0)).getDouble(); + final double b0 = NumericValue.asNumber(lv.get(1)).getDouble(); + final long maxiter = NumericValue.asNumber(lv.get(2)).getLong(); double a = 0.0D; double b = 0.0D; long iter = 0; - while(a*a+b*b<4 && iter < maxiter) + while (a * a + b * b < 4 && iter < maxiter) { - double temp = a*a-b*b+a0; - b = 2*a*b+b0; + final double temp = a * a - b * b + a0; + b = 2 * a * b + b0; a = temp; iter++; } - long iFinal = iter; + final long iFinal = iter; return new NumericValue(iFinal); }); expression.addFunction("max", (lv) -> { if (lv.size() == 0) - throw new InternalExpressionException("'max' requires at least one parameter"); - Value max = null; - if (lv.size()==1 && lv.get(0) instanceof ListValue) - lv = ((ListValue) lv.get(0)).getItems(); - for (Value parameter : lv) { - if (max == null || parameter.compareTo(max) > 0) max = parameter; + throw new InternalExpressionException("'max' requires at least one parameter"); + } + Value max = null; + if (lv.size() == 1 && lv.get(0) instanceof ListValue) + { + lv = ((ListValue) lv.get(0)).getItems(); + } + for (final Value parameter : lv) + { + if (max == null || parameter.compareTo(max) > 0) + { + max = parameter; + } } return max; }); @@ -113,17 +123,24 @@ public class Arithmetic { expression.addFunction("min", (lv) -> { if (lv.size() == 0) - throw new InternalExpressionException("'min' requires at least one parameter"); - Value min = null; - if (lv.size()==1 && lv.get(0) instanceof ListValue) - lv = ((ListValue) lv.get(0)).getItems(); - for (Value parameter : lv) { - if (min == null || parameter.compareTo(min) < 0) min = parameter; + throw new InternalExpressionException("'min' requires at least one parameter"); + } + Value min = null; + if (lv.size() == 1 && lv.get(0) instanceof ListValue) + { + lv = ((ListValue) lv.get(0)).getItems(); + } + for (final Value parameter : lv) + { + if (min == null || parameter.compareTo(min) < 0) + { + min = parameter; + } } return min; }); - expression.addUnaryFunction("relu", (v) -> v.compareTo(Value.ZERO) < 0 ? Value.ZERO : v); + expression.addUnaryFunction("relu", v -> v.compareTo(Value.ZERO) < 0 ? Value.ZERO : v); } } diff --git a/src/main/java/carpet/script/language/ControlFlow.java b/src/main/java/carpet/script/language/ControlFlow.java index 21fa4106..eb0aa5db 100644 --- a/src/main/java/carpet/script/language/ControlFlow.java +++ b/src/main/java/carpet/script/language/ControlFlow.java @@ -17,21 +17,25 @@ import carpet.script.value.Value; import java.util.Map; import java.util.stream.Collectors; -public class ControlFlow { - public static void apply(Expression expression) // public just to get the javadoc right +public class ControlFlow +{ + public static void apply(final Expression expression) // public just to get the javadoc right { // needs to be lazy cause of custom contextualization expression.addLazyBinaryOperator(";", Operators.precedence.get("nextop;"), true, true, t -> Context.Type.VOID, (c, t, lv1, lv2) -> { lv1.evalValue(c, Context.VOID); - Value v2 = lv2.evalValue(c, t); + final Value v2 = lv2.evalValue(c, t); return (cc, tt) -> v2; }); expression.addPureLazyFunction("then", -1, t -> Context.Type.VOID, (c, t, lv) -> { - int imax = lv.size()-1; - for (int i = 0; i < imax; i++) lv.get(i).evalValue(c, Context.VOID); - Value v = lv.get(imax).evalValue(c, t); + final int imax = lv.size() - 1; + for (int i = 0; i < imax; i++) + { + lv.get(i).evalValue(c, Context.VOID); + } + final Value v = lv.get(imax).evalValue(c, t); return (cc, tt) -> v; }); expression.addFunctionalEquivalence(";", "then"); @@ -40,78 +44,80 @@ public class ControlFlow { // obvious lazy due to conditional evaluation of arguments expression.addLazyFunction("if", (c, t, lv) -> { - if ( lv.size() < 2 ) + if (lv.size() < 2) + { throw new InternalExpressionException("'if' statement needs to have at least one condition and one case"); - for (int i=0; i ret; } } - if (lv.size()%2 == 1) + if (lv.size() % 2 == 1) { - Value ret = lv.get(lv.size() - 1).evalValue(c, t); + final Value ret = lv.get(lv.size() - 1).evalValue(c, t); return (cc, tt) -> ret; } return (cc, tt) -> Value.NULL; }); - expression.addImpureFunction("exit", (lv) -> { throw new ExitStatement(lv.size()==0?Value.NULL:lv.get(0)); }); + expression.addImpureFunction("exit", (lv) -> { + throw new ExitStatement(lv.size() == 0 ? Value.NULL : lv.get(0)); + }); - expression.addImpureFunction("throw", lv-> + expression.addImpureFunction("throw", lv -> { - switch (lv.size()) + switch (lv.size()) { - case 0: - throw new ThrowStatement(Value.NULL, Throwables.USER_DEFINED); - case 1: - throw new ThrowStatement(lv.get(0), Throwables.USER_DEFINED ); - case 2: - throw new ThrowStatement(lv.get(1), Throwables.getTypeForException(lv.get(0).getString())); - case 3: - throw new ThrowStatement(lv.get(2), Throwables.getTypeForException(lv.get(1).getString()), lv.get(0).getString()); - default: - throw new InternalExpressionException("throw() can't accept more than 3 parameters"); + case 0 -> throw new ThrowStatement(Value.NULL, Throwables.USER_DEFINED); + case 1 -> throw new ThrowStatement(lv.get(0), Throwables.USER_DEFINED); + case 2 -> throw new ThrowStatement(lv.get(1), Throwables.getTypeForException(lv.get(0).getString())); + case 3 -> throw new ThrowStatement(lv.get(2), Throwables.getTypeForException(lv.get(1).getString()), lv.get(0).getString()); + default -> throw new InternalExpressionException("throw() can't accept more than 3 parameters"); } }); // needs to be lazy since execution of parameters but first one are conditional expression.addLazyFunction("try", (c, t, lv) -> { - if (lv.size()==0) + if (lv.size() == 0) + { throw new InternalExpressionException("'try' needs at least an expression block, and either a catch_epr, or a number of pairs of filters and catch_expr"); + } try { - Value retval = lv.get(0).evalValue(c, t); + final Value retval = lv.get(0).evalValue(c, t); return (c_, t_) -> retval; } - catch (ProcessedThrowStatement ret) + catch (final ProcessedThrowStatement ret) { if (lv.size() == 1) { if (!ret.thrownExceptionType.isUserException()) + { throw ret; + } return (c_, t_) -> Value.NULL; } if (lv.size() > 3 && lv.size() % 2 == 0) { throw new InternalExpressionException("Try-catch block needs the code to run, and either a catch expression for user thrown exceptions, or a number of pairs of filters and catch expressions"); } - + Value val = null; // This is always assigned at some point, just the compiler doesn't know - - LazyValue __ = c.getVariable("_"); + + final LazyValue __ = c.getVariable("_"); c.setVariable("_", (__c, __t) -> ret.data.reboundedTo("_")); - LazyValue _trace = c.getVariable("_trace"); + final LazyValue _trace = c.getVariable("_trace"); c.setVariable("_trace", (__c, __t) -> MapValue.wrap(Map.of( StringValue.of("stack"), ListValue.wrap(ret.stack.stream().map(f -> ListValue.of( StringValue.of(f.getModule().name()), StringValue.of(f.getString()), - NumericValue.of(f.getToken().lineno+1), - NumericValue.of(f.getToken().linepos+1) + NumericValue.of(f.getToken().lineno + 1), + NumericValue.of(f.getToken().linepos + 1) ))), StringValue.of("locals"), MapValue.wrap(ret.context.variables.entrySet().stream().filter(e -> !e.getKey().equals("_trace")).collect(Collectors.toMap( @@ -120,20 +126,22 @@ public class ControlFlow { ))), StringValue.of("token"), ListValue.of( StringValue.of(ret.token.surface), - NumericValue.of(ret.token.lineno+1), - NumericValue.of(ret.token.linepos+1) + NumericValue.of(ret.token.lineno + 1), + NumericValue.of(ret.token.linepos + 1) ) ))); if (lv.size() == 2) { if (ret.thrownExceptionType.isUserException()) + { val = lv.get(1).evalValue(c, t); + } } else { int pointer = 1; - while (pointer < lv.size() -1) + while (pointer < lv.size() - 1) { if (ret.thrownExceptionType.isRelevantFor(lv.get(pointer).evalValue(c).getString())) { @@ -145,14 +153,18 @@ public class ControlFlow { } c.setVariable("_", __); if (_trace != null) + { c.setVariable("_trace", _trace); + } else + { c.delVariable("_trace"); + } if (val == null) // not handled { throw ret; } - Value retval = val; + final Value retval = val; return (c_, t_) -> retval; } }); diff --git a/src/main/java/carpet/script/language/DataStructures.java b/src/main/java/carpet/script/language/DataStructures.java index 1b9ed5e4..b70dd079 100644 --- a/src/main/java/carpet/script/language/DataStructures.java +++ b/src/main/java/carpet/script/language/DataStructures.java @@ -25,42 +25,42 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -public class DataStructures { - public static void apply(Expression expression) +public class DataStructures +{ + public static void apply(final Expression expression) { expression.addFunction("l", lv -> - { - if (lv.size() == 1 && lv.get(0) instanceof LazyListValue) - return ListValue.wrap(((LazyListValue) lv.get(0)).unroll()); - return new ListValue.ListConstructorValue(lv); - }); + lv.size() == 1 && lv.get(0) instanceof final LazyListValue llv + ? ListValue.wrap(llv.unroll()) + : new ListValue.ListConstructorValue(lv)); expression.addFunction("join", (lv) -> { if (lv.size() < 2) + { throw new InternalExpressionException("'join' takes at least 2 arguments"); - String delimiter = lv.get(0).getString(); - List toJoin; - if (lv.size()==2 && lv.get(1) instanceof LazyListValue) - { - toJoin = ((LazyListValue) lv.get(1)).unroll(); - } - else if (lv.size() == 2 && lv.get(1) instanceof ListValue) + final String delimiter = lv.get(0).getString(); + final List toJoin; + if (lv.size() == 2 && lv.get(1) instanceof final LazyListValue llv) { - toJoin = new ArrayList<>(((ListValue)lv.get(1)).getItems()); + toJoin = llv.unroll(); + } + else if (lv.size() == 2 && lv.get(1) instanceof final ListValue llv) + { + toJoin = new ArrayList<>(llv.getItems()); } else { - toJoin = lv.subList(1,lv.size()); + toJoin = lv.subList(1, lv.size()); } return new StringValue(toJoin.stream().map(Value::getString).collect(Collectors.joining(delimiter))); }); expression.addFunction("split", (lv) -> { - Value delimiter; - Value hwat; + final Value delimiter; + final Value hwat; if (lv.size() == 1) { hwat = lv.get(0); @@ -80,23 +80,26 @@ public class DataStructures { expression.addFunction("slice", (lv) -> { - if (lv.size() != 2 && lv.size() != 3) + { throw new InternalExpressionException("'slice' takes 2 or 3 arguments"); - Value hwat = lv.get(0); - long from = NumericValue.asNumber(lv.get(1)).getLong(); + } + final Value hwat = lv.get(0); + final long from = NumericValue.asNumber(lv.get(1)).getLong(); Long to = null; - if (lv.size()== 3) + if (lv.size() == 3) + { to = NumericValue.asNumber(lv.get(2)).getLong(); + } return hwat.slice(from, to); }); expression.addFunction("sort", (lv) -> { List toSort = lv; - if (lv.size()==1 && lv.get(0) instanceof ListValue) + if (lv.size() == 1 && lv.get(0) instanceof final ListValue llv) { - toSort = new ArrayList<>(((ListValue)lv.get(0)).getItems()); + toSort = new ArrayList<>(llv.getItems()); } Collections.sort(toSort); return ListValue.wrap(toSort); @@ -106,30 +109,34 @@ public class DataStructures { expression.addLazyFunction("sort_key", (c, t, lv) -> //get working with iterators { if (lv.size() == 0) + { throw new InternalExpressionException("First argument for 'sort_key' should be a List"); - Value v = lv.get(0).evalValue(c); - if (!(v instanceof ListValue)) + } + final Value v = lv.get(0).evalValue(c); + if (!(v instanceof final ListValue list)) + { throw new InternalExpressionException("First argument for 'sort_key' should be a List"); - List toSort = new ArrayList<>(((ListValue) v).getItems()); - if (lv.size()==1) + } + final List toSort = new ArrayList<>(list.getItems()); + if (lv.size() == 1) { Collections.shuffle(toSort); - Value ret = ListValue.wrap(toSort); + final Value ret = ListValue.wrap(toSort); return (_c, _t) -> ret; } - LazyValue sortKey = lv.get(1); + final LazyValue sortKey = lv.get(1); //scoping - LazyValue __ = c.getVariable("_"); - Collections.sort(toSort,(v1, v2) -> { - c.setVariable("_",(cc, tt) -> v1); - Value ev1 = sortKey.evalValue(c); - c.setVariable("_",(cc, tt) -> v2); - Value ev2 = sortKey.evalValue(c); + final LazyValue __ = c.getVariable("_"); + toSort.sort((v1, v2) -> { + c.setVariable("_", (cc, tt) -> v1); + final Value ev1 = sortKey.evalValue(c); + c.setVariable("_", (cc, tt) -> v2); + final Value ev2 = sortKey.evalValue(c); return ev1.compareTo(ev2); }); //revering scope c.setVariable("_", __); - Value ret = ListValue.wrap(toSort); + final Value ret = ListValue.wrap(toSort); return (cc, tt) -> ret; }); @@ -138,9 +145,11 @@ public class DataStructures { NumericValue from = Value.ZERO; NumericValue to; NumericValue step = Value.ONE; - int argsize = lv.size(); + final int argsize = lv.size(); if (argsize == 0 || argsize > 3) - throw new InternalExpressionException("'range' accepts from 1 to 3 arguments, not "+argsize); + { + throw new InternalExpressionException("'range' accepts from 1 to 3 arguments, not " + argsize); + } to = NumericValue.asNumber(lv.get(0)); if (lv.size() > 1) { @@ -157,79 +166,84 @@ public class DataStructures { }); expression.addTypedContextFunction("m", -1, Context.MAPDEF, (c, t, lv) -> - { - Value ret; - if (lv.size() == 1 && lv.get(0) instanceof LazyListValue) - ret = new MapValue(((LazyListValue) lv.get(0)).unroll()); - else - ret = new MapValue(lv); - return ret; - }); + lv.size() == 1 && lv.get(0) instanceof final LazyListValue llv + ? new MapValue(llv.unroll()) + : new MapValue(lv) + ); expression.addUnaryFunction("keys", v -> - { - if (v instanceof MapValue) - return new ListValue(((MapValue) v).getMap().keySet()); - return Value.NULL; - }); + v instanceof final MapValue map + ? new ListValue(map.getMap().keySet()) + : Value.NULL + ); expression.addUnaryFunction("values", v -> - { - if (v instanceof MapValue) - return new ListValue(((MapValue) v).getMap().values()); - return Value.NULL; - }); + v instanceof final MapValue map + ? new ListValue(map.getMap().values()) + : Value.NULL + ); expression.addUnaryFunction("pairs", v -> - { - if (v instanceof MapValue) - return ListValue.wrap(((MapValue) v).getMap().entrySet().stream().map( - (p) -> ListValue.of(p.getKey(), p.getValue()) - )); - return Value.NULL; - }); + v instanceof final MapValue map + ? ListValue.wrap(map.getMap().entrySet().stream().map(p -> ListValue.of(p.getKey(), p.getValue()))) + : Value.NULL); - expression.addBinaryContextOperator(":", Operators.precedence.get("attribute~:"),true, true, false, (ctx, t, container, address) -> + expression.addBinaryContextOperator(":", Operators.precedence.get("attribute~:"), true, true, false, (ctx, t, container, address) -> { - if (container instanceof LContainerValue) + if (container instanceof final LContainerValue lcv) { - ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer(); - if (outerContainer == null) return LContainerValue.NULL_CONTAINER; - Value innerContainer = outerContainer.get(((LContainerValue) container).getAddress()); - if (!(innerContainer instanceof ContainerValueInterface)) return LContainerValue.NULL_CONTAINER; - return new LContainerValue((ContainerValueInterface) innerContainer, address); + final ContainerValueInterface outerContainer = lcv.container(); + if (outerContainer == null) + { + return LContainerValue.NULL_CONTAINER; + } + return outerContainer.get(lcv.address()) instanceof final ContainerValueInterface cvi + ? new LContainerValue(cvi, address) + : LContainerValue.NULL_CONTAINER; } - if (!(container instanceof ContainerValueInterface)) + if (!(container instanceof final ContainerValueInterface cvi)) + { return t == Context.LVALUE ? LContainerValue.NULL_CONTAINER : Value.NULL; - if (t != Context.LVALUE) return ((ContainerValueInterface) container).get(address); - return new LContainerValue((ContainerValueInterface) container, address); + } + return t != Context.LVALUE ? cvi.get(address) : new LContainerValue(cvi, address); }); // lazy cause conditional typing - questionable expression.addLazyFunction("get", (c, t, lv) -> { if (lv.size() == 0) + { throw new InternalExpressionException("'get' requires parameters"); + } if (lv.size() == 1) { - Value v = lv.get(0).evalValue(c, Context.LVALUE); - if (!(v instanceof LContainerValue)) + final Value v = lv.get(0).evalValue(c, Context.LVALUE); + if (!(v instanceof final LContainerValue lcv)) + { return LazyValue.NULL; - ContainerValueInterface container = ((LContainerValue) v).getContainer(); + } + final ContainerValueInterface container = lcv.container(); if (container == null) + { return LazyValue.NULL; - Value ret = container.get(((LContainerValue) v).getAddress()); + } + final Value ret = container.get(lcv.address()); return (cc, tt) -> ret; } Value container = lv.get(0).evalValue(c); for (int i = 1; i < lv.size(); i++) { - if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; - container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); + if (!(container instanceof final ContainerValueInterface cvi)) + { + return (cc, tt) -> Value.NULL; + } + container = cvi.get(lv.get(i).evalValue(c)); } if (container == null) + { return (cc, tt) -> Value.NULL; - Value finalContainer = container; + } + final Value finalContainer = container; return (cc, tt) -> finalContainer; }); @@ -237,66 +251,77 @@ public class DataStructures { expression.addLazyFunction("has", (c, t, lv) -> { if (lv.size() == 0) + { throw new InternalExpressionException("'has' requires parameters"); + } if (lv.size() == 1) { - Value v = lv.get(0).evalValue(c, Context.LVALUE); - if (!(v instanceof LContainerValue)) + final Value v = lv.get(0).evalValue(c, Context.LVALUE); + if (!(v instanceof final LContainerValue lcv)) + { return LazyValue.NULL; - ContainerValueInterface container = ((LContainerValue) v).getContainer(); + } + final ContainerValueInterface container = lcv.container(); if (container == null) + { return LazyValue.NULL; - Value ret = BooleanValue.of(container.has(((LContainerValue) v).getAddress())); + } + final Value ret = BooleanValue.of(container.has(lcv.address())); return (cc, tt) -> ret; } Value container = lv.get(0).evalValue(c); - for (int i = 1; i < lv.size()-1; i++) + for (int i = 1; i < lv.size() - 1; i++) { - if (!(container instanceof ContainerValueInterface)) return LazyValue.NULL; - container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); + if (!(container instanceof final ContainerValueInterface cvi)) + { + return LazyValue.NULL; + } + container = cvi.get(lv.get(i).evalValue(c)); } - if (!(container instanceof ContainerValueInterface)) + if (!(container instanceof final ContainerValueInterface cvi)) + { return LazyValue.NULL; - Value ret = BooleanValue.of(((ContainerValueInterface) container).has(lv.get(lv.size()-1).evalValue(c))); + } + final Value ret = BooleanValue.of(cvi.has(lv.get(lv.size() - 1).evalValue(c))); return (cc, tt) -> ret; }); // same as `get` expression.addLazyFunction("put", (c, t, lv) -> { - if(lv.size()<2) + if (lv.size() < 2) { throw new InternalExpressionException("'put' takes at least three arguments, a container, address, and values to insert at that index"); } - Value container = lv.get(0).evalValue(c, Context.LVALUE); - if (container instanceof LContainerValue) + final Value container = lv.get(0).evalValue(c, Context.LVALUE); + if (container instanceof final LContainerValue lcv) { - ContainerValueInterface internalContainer = ((LContainerValue) container).getContainer(); + final ContainerValueInterface internalContainer = lcv.container(); if (internalContainer == null) { return LazyValue.NULL; } - Value address = ((LContainerValue) container).getAddress(); - Value what = lv.get(1).evalValue(c); - Value retVal = BooleanValue.of((lv.size() > 2) + final Value address = lcv.address(); + final Value what = lv.get(1).evalValue(c); + final Value retVal = BooleanValue.of((lv.size() > 2) ? internalContainer.put(address, what, lv.get(2).evalValue(c)) : internalContainer.put(address, what)); return (cc, tt) -> retVal; } - if(lv.size()<3) + if (lv.size() < 3) { throw new InternalExpressionException("'put' takes at least three arguments, a container, address, and values to insert at that index"); } - if (!(container instanceof ContainerValueInterface)) + if (!(container instanceof final ContainerValueInterface cvi)) { return LazyValue.NULL; } - Value where = lv.get(1).evalValue(c); - Value what = lv.get(2).evalValue(c); - Value retVal = BooleanValue.of((lv.size()>3) - ? ((ContainerValueInterface) container).put(where, what, lv.get(3).evalValue(c)) - : ((ContainerValueInterface) container).put(where, what)); + final Value where = lv.get(1).evalValue(c); + final Value what = lv.get(2).evalValue(c); + final Value retVal = BooleanValue.of((lv.size() > 3) + ? cvi.put(where, what, lv.get(3).evalValue(c)) + : cvi.put(where, what)); return (cc, tt) -> retVal; }); @@ -304,44 +329,61 @@ public class DataStructures { expression.addLazyFunction("delete", (c, t, lv) -> { if (lv.size() == 0) + { throw new InternalExpressionException("'delete' requires parameters"); + } if (lv.size() == 1) { - Value v = lv.get(0).evalValue(c, Context.LVALUE); - if (!(v instanceof LContainerValue)) + final Value v = lv.get(0).evalValue(c, Context.LVALUE); + if (!(v instanceof final LContainerValue lcv)) + { return LazyValue.NULL; - ContainerValueInterface container = ((LContainerValue) v).getContainer(); + } + final ContainerValueInterface container = lcv.container(); if (container == null) + { return LazyValue.NULL; - Value ret = BooleanValue.of(container.delete(((LContainerValue) v).getAddress())); + } + final Value ret = BooleanValue.of(container.delete(lcv.address())); return (cc, tt) -> ret; } Value container = lv.get(0).evalValue(c); - for (int i = 1; i < lv.size()-1; i++) + for (int i = 1; i < lv.size() - 1; i++) { - if (!(container instanceof ContainerValueInterface)) return LazyValue.NULL; - container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); + if (!(container instanceof final ContainerValueInterface cvi)) + { + return LazyValue.NULL; + } + container = cvi.get(lv.get(i).evalValue(c)); } - if (!(container instanceof ContainerValueInterface)) + if (!(container instanceof final ContainerValueInterface cvi)) + { return LazyValue.NULL; - Value ret = BooleanValue.of(((ContainerValueInterface) container).delete(lv.get(lv.size()-1).evalValue(c))); + } + final Value ret = BooleanValue.of(cvi.delete(lv.get(lv.size() - 1).evalValue(c))); return (cc, tt) -> ret; }); expression.addUnaryFunction("encode_b64", v -> StringValue.of(Base64.getEncoder().encodeToString(v.getString().getBytes(StandardCharsets.UTF_8)))); expression.addUnaryFunction("decode_b64", v -> { - try { + try + { return StringValue.of(new String(Base64.getDecoder().decode(v.getString()), StandardCharsets.UTF_8)); - } catch (IllegalArgumentException iae){ + } + catch (final IllegalArgumentException iae) + { throw new ThrowStatement("Invalid b64 string: " + v.getString(), Throwables.B64_ERROR); } }); expression.addUnaryFunction("encode_json", v -> StringValue.of(v.toJson().toString())); expression.addUnaryFunction("decode_json", v -> { - try { + try + { return Auxiliary.GSON.fromJson(v.getString(), Value.class); - } catch (JsonParseException jpe){ + } + catch (final JsonParseException jpe) + { throw new ThrowStatement("Invalid json string: " + v.getString(), Throwables.JSON_ERROR); } }); diff --git a/src/main/java/carpet/script/language/Functions.java b/src/main/java/carpet/script/language/Functions.java index 28953ed7..93e1196e 100644 --- a/src/main/java/carpet/script/language/Functions.java +++ b/src/main/java/carpet/script/language/Functions.java @@ -19,61 +19,70 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -public class Functions { - public static void apply(Expression expression) // public just to get the javadoc right +public class Functions +{ + public static void apply(final Expression expression) // public just to get the javadoc right { // artificial construct to handle user defined functions and function definitions expression.addContextFunction("import", -1, (c, t, lv) -> { - if (lv.size() < 1) throw new InternalExpressionException("'import' needs at least a module name to import, and list of values to import"); + if (lv.size() < 1) + { + throw new InternalExpressionException("'import' needs at least a module name to import, and list of values to import"); + } String moduleName = lv.get(0).getString(); c.host.importModule(c, moduleName); moduleName = moduleName.toLowerCase(Locale.ROOT); if (lv.size() > 1) + { c.host.importNames(c, expression.module, moduleName, lv.subList(1, lv.size()).stream().map(Value::getString).toList()); - if (t == Context.VOID) - return Value.NULL; - return ListValue.wrap(c.host.availableImports(moduleName).map(StringValue::new)); + } + return t == Context.VOID ? Value.NULL : ListValue.wrap(c.host.availableImports(moduleName).map(StringValue::new)); }); // needs to be lazy because of custom context of execution of arguments as a signature - expression.addCustomFunction("call", new Fluff.AbstractLazyFunction(-1, "call") { + expression.addCustomFunction("call", new Fluff.AbstractLazyFunction(-1, "call") + { @Override - public LazyValue lazyEval(Context c, Context.Type t, Expression expr, Tokenizer.Token tok, List lv) + public LazyValue lazyEval(final Context c, final Context.Type t, final Expression expr, final Tokenizer.Token tok, final List lv) { if (lv.size() == 0) + { throw new InternalExpressionException("'call' expects at least function name to call"); + } //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 { - List args = Fluff.AbstractFunction.unpackLazy(lv, c, Context.NONE); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, args, 0, false, true); - FunctionValue fun = functionArgument.function; + final List args = Fluff.AbstractFunction.unpackLazy(lv, c, Context.NONE); + final FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, args, 0, false, true); + final FunctionValue fun = functionArgument.function; return fun.callInContext(c, t, functionArgument.args); } // gimme signature - String name = lv.get(0).evalValue(c, Context.NONE).getString(); - List args = new ArrayList<>(); - List globals = new ArrayList<>(); + final String name = lv.get(0).evalValue(c, Context.NONE).getString(); + final List args = new ArrayList<>(); + final List globals = new ArrayList<>(); String varArgs = null; for (int i = 1; i < lv.size(); i++) { - Value v = lv.get(i).evalValue(c, Context.LOCALIZATION); + final Value v = lv.get(i).evalValue(c, Context.LOCALIZATION); if (!v.isBound()) { throw new InternalExpressionException("Only variables can be used in function signature, not " + v.getString()); } - if (v instanceof FunctionAnnotationValue) + if (v instanceof final FunctionAnnotationValue fav) { - if (((FunctionAnnotationValue) v).type == FunctionAnnotationValue.Type.GLOBAL) + if (fav.type == FunctionAnnotationValue.Type.GLOBAL) { globals.add(v.boundVariable); } else { if (varArgs != null) - throw new InternalExpressionException("Variable argument identifier is already defined as "+varArgs+", trying to overwrite with "+v.boundVariable); + { + throw new InternalExpressionException("Variable argument identifier is already defined as " + varArgs + ", trying to overwrite with " + v.boundVariable); + } varArgs = v.boundVariable; } } @@ -82,7 +91,7 @@ public class Functions { args.add(v.boundVariable); } } - Value retval = new FunctionSignatureValue(name, args, varArgs, globals); + final Value retval = new FunctionSignatureValue(name, args, varArgs, globals); return (cc, tt) -> retval; } @@ -93,14 +102,15 @@ public class Functions { } @Override - public boolean transitive() { + public boolean transitive() + { return false; } @Override - public Context.Type staticType(Context.Type outerType) + public Context.Type staticType(final Context.Type outerType) { - return outerType==Context.SIGNATURE?Context.LOCALIZATION:Context.NONE; + return outerType == Context.SIGNATURE ? Context.LOCALIZATION : Context.NONE; } }); @@ -108,7 +118,9 @@ public class Functions { expression.addContextFunction("outer", 1, (c, t, lv) -> { if (t != Context.LOCALIZATION) + { throw new InternalExpressionException("Outer scoping of variables is only possible in function signatures."); + } return new FunctionAnnotationValue(lv.get(0), FunctionAnnotationValue.Type.GLOBAL); }); @@ -118,16 +130,20 @@ public class Functions { { if (type == Context.MAPDEF) { - Value result = ListValue.of(lv1.evalValue(c), lv2.evalValue(c)); + final Value result = ListValue.of(lv1.evalValue(c), lv2.evalValue(c)); return (cc, tt) -> result; } - Value v1 = lv1.evalValue(c, Context.SIGNATURE); - if (!(v1 instanceof FunctionSignatureValue sign)) + final Value v1 = lv1.evalValue(c, Context.SIGNATURE); + if (!(v1 instanceof final FunctionSignatureValue sign)) + { throw new InternalExpressionException("'->' operator requires a function signature on the LHS"); - Value result = expression.createUserDefinedFunction(c, sign.getName(), e, t, sign.getArgs(), sign.getVarArgs(), sign.getGlobals(), lv2); + } + final Value result = expression.createUserDefinedFunction(c, sign.identifier(), e, t, sign.arguments(), sign.varArgs(), sign.globals(), lv2); return (cc, tt) -> result; }); - expression.addImpureFunction("return", (lv) -> { throw new ReturnStatement(lv.size()==0?Value.NULL:lv.get(0));} ); + expression.addImpureFunction("return", (lv) -> { + throw new ReturnStatement(lv.size() == 0 ? Value.NULL : lv.get(0)); + }); } } diff --git a/src/main/java/carpet/script/language/Loops.java b/src/main/java/carpet/script/language/Loops.java index 4261bb61..36e4b626 100644 --- a/src/main/java/carpet/script/language/Loops.java +++ b/src/main/java/carpet/script/language/Loops.java @@ -15,55 +15,74 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class Loops { - public static void apply(Expression expression) +public class Loops +{ + public static void apply(final Expression expression) { // condition and expression will get a bound '_i' // returns last successful expression or false // while(cond, limit, expr) => ?? expression.addImpureFunction("break", lv -> { - if (lv.size()==0) throw new BreakStatement(null); - if (lv.size()==1) throw new BreakStatement(lv.get(0)); + if (lv.size() == 0) + { + throw new BreakStatement(null); + } + if (lv.size() == 1) + { + throw new BreakStatement(lv.get(0)); + } throw new InternalExpressionException("'break' can only be called with zero or one argument"); }); expression.addImpureFunction("continue", lv -> { - if (lv.size()==0) throw new ContinueStatement(null); - if (lv.size()==1) throw new ContinueStatement(lv.get(0)); + if (lv.size() == 0) + { + throw new ContinueStatement(null); + } + if (lv.size() == 1) + { + throw new ContinueStatement(lv.get(0)); + } throw new InternalExpressionException("'continue' can only be called with zero or one argument"); }); // lazy expression.addLazyFunction("while", 3, (c, t, lv) -> { - long limit = NumericValue.asNumber(lv.get(1).evalValue(c)).getLong(); - LazyValue condition = lv.get(0); - LazyValue expr = lv.get(2); + final long limit = NumericValue.asNumber(lv.get(1).evalValue(c)).getLong(); + final LazyValue condition = lv.get(0); + final LazyValue expr = lv.get(2); long i = 0; Value lastOne = Value.NULL; //scoping - LazyValue _val = c.getVariable("_"); - c.setVariable("_",(cc, tt) -> new NumericValue(0).bindTo("_")); - while (i new NumericValue(0).bindTo("_")); + while (i < limit && condition.evalValue(c, Context.BOOLEAN).getBoolean()) { try { lastOne = expr.evalValue(c, t); } - catch (BreakStatement | ContinueStatement stmt) + catch (final BreakStatement | ContinueStatement stmt) { - if (stmt.retval != null) lastOne = stmt.retval; - if (stmt instanceof BreakStatement) break; + if (stmt.retval != null) + { + lastOne = stmt.retval; + } + if (stmt instanceof BreakStatement) + { + break; + } } i++; - long seriously = i; + final long seriously = i; c.setVariable("_", (cc, tt) -> new NumericValue(seriously).bindTo("_")); } //revering scope c.setVariable("_", _val); - Value lastValueNoKidding = lastOne; + final Value lastValueNoKidding = lastOne; return (cc, tt) -> lastValueNoKidding; }); @@ -71,28 +90,34 @@ public class Loops { // expr receives bounded variable '_' indicating iteration expression.addLazyFunction("loop", 2, (c, t, lv) -> { - long limit = NumericValue.asNumber(lv.get(0).evalValue(c, Context.NONE)).getLong(); + final long limit = NumericValue.asNumber(lv.get(0).evalValue(c, Context.NONE)).getLong(); Value lastOne = Value.NULL; - LazyValue expr = lv.get(1); + final LazyValue expr = lv.get(1); //scoping - LazyValue _val = c.getVariable("_"); - for (long i=0; i < limit; i++) + final LazyValue _val = c.getVariable("_"); + for (long i = 0; i < limit; i++) { - long whyYouAsk = i; + final long whyYouAsk = i; c.setVariable("_", (cc, tt) -> new NumericValue(whyYouAsk).bindTo("_")); try { lastOne = expr.evalValue(c, t); } - catch (BreakStatement | ContinueStatement stmt) + catch (final BreakStatement | ContinueStatement stmt) { - if (stmt.retval != null) lastOne = stmt.retval; - if (stmt instanceof BreakStatement) break; + if (stmt.retval != null) + { + lastOne = stmt.retval; + } + if (stmt instanceof BreakStatement) + { + break; + } } } //revering scope c.setVariable("_", _val); - Value trulyLastOne = lastOne; + final Value trulyLastOne = lastOne; return (cc, tt) -> trulyLastOne; }); @@ -100,31 +125,39 @@ public class Loops { // receives bounded variable '_' with the expression expression.addLazyFunction("map", 2, (c, t, lv) -> { - Value rval= lv.get(0).evalValue(c, Context.NONE); - if (rval.isNull()) return ListValue.lazyEmpty(); - if (!(rval instanceof AbstractListValue)) - throw new InternalExpressionException("First argument of 'map' function should be a list or iterator"); - Iterator iterator = ((AbstractListValue) rval).iterator(); - LazyValue expr = lv.get(1); - //scoping - LazyValue _val = c.getVariable("_"); - LazyValue _iter = c.getVariable("_i"); - List result = new ArrayList<>(); - for (int i=0; iterator.hasNext(); i++) + final Value rval = lv.get(0).evalValue(c, Context.NONE); + if (rval.isNull()) { - Value next = iterator.next(); - String var = next.boundVariable; + return ListValue.lazyEmpty(); + } + if (!(rval instanceof final AbstractListValue alv)) + { + throw new InternalExpressionException("First argument of 'map' function should be a list or iterator"); + } + final Iterator iterator = alv.iterator(); + final LazyValue expr = lv.get(1); + //scoping + final LazyValue _val = c.getVariable("_"); + final LazyValue _iter = c.getVariable("_i"); + final List result = new ArrayList<>(); + for (int i = 0; iterator.hasNext(); i++) + { + final Value next = iterator.next(); + final String var = next.boundVariable; next.bindTo("_"); - int doYouReally = i; + final int doYouReally = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(doYouReally).bindTo("_i")); try { result.add(expr.evalValue(c, t)); } - catch (BreakStatement | ContinueStatement stmt) + catch (final BreakStatement | ContinueStatement stmt) { - if (stmt.retval != null) result.add(stmt.retval); + if (stmt.retval != null) + { + result.add(stmt.retval); + } if (stmt instanceof BreakStatement) { next.boundVariable = var; @@ -134,11 +167,11 @@ public class Loops { next.boundVariable = var; } ((AbstractListValue) rval).fatality(); - Value ret = ListValue.wrap(result); + final Value ret = ListValue.wrap(result); //revering scope c.setVariable("_", _val); c.setVariable("_i", _iter); - return (cc, tt) -> ret; + return (cc, tt) -> ret; }); // grep(list or num, expr) => list @@ -146,32 +179,42 @@ public class Loops { // produces list of values for which the expression is true expression.addLazyFunction("filter", 2, (c, t, lv) -> { - Value rval= lv.get(0).evalValue(c, Context.NONE); - if (rval.isNull()) return ListValue.lazyEmpty(); - if (!(rval instanceof AbstractListValue)) - throw new InternalExpressionException("First argument of 'filter' function should be a list or iterator"); - Iterator iterator = ((AbstractListValue) rval).iterator(); - LazyValue expr = lv.get(1); - //scoping - LazyValue _val = c.getVariable("_"); - LazyValue _iter = c.getVariable("_i"); - List result = new ArrayList<>(); - for (int i=0; iterator.hasNext(); i++) + final Value rval = lv.get(0).evalValue(c, Context.NONE); + if (rval.isNull()) { - Value next = iterator.next(); - String var = next.boundVariable; + return ListValue.lazyEmpty(); + } + if (!(rval instanceof final AbstractListValue alv)) + { + throw new InternalExpressionException("First argument of 'filter' function should be a list or iterator"); + } + final Iterator iterator = alv.iterator(); + final LazyValue expr = lv.get(1); + //scoping + final LazyValue _val = c.getVariable("_"); + final LazyValue _iter = c.getVariable("_i"); + final List result = new ArrayList<>(); + for (int i = 0; iterator.hasNext(); i++) + { + final Value next = iterator.next(); + final String var = next.boundVariable; next.bindTo("_"); - int seriously = i; + final int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); try { - if(expr.evalValue(c, Context.BOOLEAN).getBoolean()) + if (expr.evalValue(c, Context.BOOLEAN).getBoolean()) + { result.add(next); + } } - catch (BreakStatement | ContinueStatement stmt) + catch (final BreakStatement | ContinueStatement stmt) { - if (stmt.retval != null && stmt.retval.getBoolean()) result.add(next); + if (stmt.retval != null && stmt.retval.getBoolean()) + { + result.add(next); + } if (stmt instanceof BreakStatement) { next.boundVariable = var; @@ -181,7 +224,7 @@ public class Loops { next.boundVariable = var; } ((AbstractListValue) rval).fatality(); - Value ret = ListValue.wrap(result); + final Value ret = ListValue.wrap(result); //revering scope c.setVariable("_", _val); c.setVariable("_i", _iter); @@ -193,41 +236,45 @@ public class Loops { // returns first element on the list for which the expr is true expression.addLazyFunction("first", 2, (c, t, lv) -> { - - Value rval= lv.get(0).evalValue(c, Context.NONE); - if (rval.isNull()) return LazyValue.NULL; - if (!(rval instanceof AbstractListValue)) - throw new InternalExpressionException("First argument of 'first' function should be a list or iterator"); - Iterator iterator = ((AbstractListValue) rval).iterator(); - LazyValue expr = lv.get(1); - //scoping - LazyValue _val = c.getVariable("_"); - LazyValue _iter = c.getVariable("_i"); - Value result = Value.NULL; - for (int i=0; iterator.hasNext(); i++) + final Value rval = lv.get(0).evalValue(c, Context.NONE); + if (rval.isNull()) { - Value next = iterator.next(); - String var = next.boundVariable; + return LazyValue.NULL; + } + if (!(rval instanceof final AbstractListValue alv)) + { + throw new InternalExpressionException("First argument of 'first' function should be a list or iterator"); + } + final Iterator iterator = alv.iterator(); + final LazyValue expr = lv.get(1); + //scoping + final LazyValue _val = c.getVariable("_"); + final LazyValue _iter = c.getVariable("_i"); + Value result = Value.NULL; + for (int i = 0; iterator.hasNext(); i++) + { + final Value next = iterator.next(); + final String var = next.boundVariable; next.bindTo("_"); - int seriously = i; + final int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); try { - if(expr.evalValue(c, Context.BOOLEAN).getBoolean()) + if (expr.evalValue(c, Context.BOOLEAN).getBoolean()) { result = next; next.boundVariable = var; break; } } - catch (BreakStatement stmt) + catch (final BreakStatement stmt) { - result = stmt.retval == null? next : stmt.retval; + result = stmt.retval == null ? next : stmt.retval; next.boundVariable = var; break; } - catch (ContinueStatement ignored) + catch (final ContinueStatement ignored) { throw new InternalExpressionException("'continue' inside 'first' function has no sense"); } @@ -235,7 +282,7 @@ public class Loops { } //revering scope ((AbstractListValue) rval).fatality(); - Value whyWontYouTrustMeJava = result; + final Value whyWontYouTrustMeJava = result; c.setVariable("_", _val); c.setVariable("_i", _iter); return (cc, tt) -> whyWontYouTrustMeJava; @@ -246,25 +293,30 @@ public class Loops { // returns true if expr is true for all items expression.addLazyFunction("all", 2, (c, t, lv) -> { - Value rval= lv.get(0).evalValue(c, Context.NONE); - if (rval.isNull()) return LazyValue.TRUE; - if (!(rval instanceof AbstractListValue)) - throw new InternalExpressionException("First argument of 'all' function should be a list or iterator"); - Iterator iterator = ((AbstractListValue) rval).iterator(); - LazyValue expr = lv.get(1); - //scoping - LazyValue _val = c.getVariable("_"); - LazyValue _iter = c.getVariable("_i"); - LazyValue result = LazyValue.TRUE; - for (int i=0; iterator.hasNext(); i++) + final Value rval = lv.get(0).evalValue(c, Context.NONE); + if (rval.isNull()) { - Value next = iterator.next(); - String var = next.boundVariable; + return LazyValue.TRUE; + } + if (!(rval instanceof final AbstractListValue alv)) + { + throw new InternalExpressionException("First argument of 'all' function should be a list or iterator"); + } + final Iterator iterator = alv.iterator(); + final LazyValue expr = lv.get(1); + //scoping + final LazyValue _val = c.getVariable("_"); + final LazyValue _iter = c.getVariable("_i"); + LazyValue result = LazyValue.TRUE; + for (int i = 0; iterator.hasNext(); i++) + { + final Value next = iterator.next(); + final String var = next.boundVariable; next.bindTo("_"); - int seriously = i; + final int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); - if(!expr.evalValue(c, Context.BOOLEAN).getBoolean()) + if (!expr.evalValue(c, Context.BOOLEAN).getBoolean()) { result = LazyValue.FALSE; next.boundVariable = var; @@ -282,10 +334,10 @@ public class Loops { // runs traditional for(init, condition, increment, body) tri-argument for loop with body in between expression.addLazyFunction("c_for", 4, (c, t, lv) -> { - LazyValue initial = lv.get(0); - LazyValue condition = lv.get(1); - LazyValue increment = lv.get(2); - LazyValue body = lv.get(3); + final LazyValue initial = lv.get(0); + final LazyValue condition = lv.get(1); + final LazyValue increment = lv.get(2); + final LazyValue body = lv.get(3); int iterations = 0; for (initial.evalValue(c, Context.VOID); condition.evalValue(c, Context.BOOLEAN).getBoolean(); increment.evalValue(c, Context.VOID)) { @@ -293,16 +345,16 @@ public class Loops { { body.evalValue(c, Context.VOID); } - catch (BreakStatement stmt) + catch (final BreakStatement stmt) { break; } - catch (ContinueStatement ignored) + catch (final ContinueStatement ignored) { } iterations++; } - int finalIterations = iterations; + final int finalIterations = iterations; return (cc, tt) -> new NumericValue(finalIterations); }); @@ -311,22 +363,27 @@ public class Loops { // can be substituted for first and all, but first is more efficient and all doesn't require knowing list size expression.addLazyFunction("for", 2, (c, t, lv) -> { - Value rval= lv.get(0).evalValue(c, Context.NONE); - if (rval.isNull()) return LazyValue.ZERO; - if (!(rval instanceof AbstractListValue)) - throw new InternalExpressionException("First argument of 'for' function should be a list or iterator"); - Iterator iterator = ((AbstractListValue) rval).iterator(); - LazyValue expr = lv.get(1); - //scoping - LazyValue _val = c.getVariable("_"); - LazyValue _ite = c.getVariable("_i"); - int successCount = 0; - for (int i=0; iterator.hasNext(); i++) + final Value rval = lv.get(0).evalValue(c, Context.NONE); + if (rval.isNull()) { - Value next = iterator.next(); - String var = next.boundVariable; + return LazyValue.ZERO; + } + if (!(rval instanceof final AbstractListValue alv)) + { + throw new InternalExpressionException("First argument of 'for' function should be a list or iterator"); + } + final Iterator iterator = alv.iterator(); + final LazyValue expr = lv.get(1); + //scoping + final LazyValue _val = c.getVariable("_"); + final LazyValue _ite = c.getVariable("_i"); + int successCount = 0; + for (int i = 0; iterator.hasNext(); i++) + { + final Value next = iterator.next(); + final String var = next.boundVariable; next.bindTo("_"); - int seriously = i; + final int seriously = i; c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); Value result = Value.FALSE; @@ -334,24 +391,29 @@ public class Loops { { result = expr.evalValue(c, t); } - catch (BreakStatement | ContinueStatement stmt) + catch (final BreakStatement | ContinueStatement stmt) { - if (stmt.retval != null) result = stmt.retval; + if (stmt.retval != null) + { + result = stmt.retval; + } if (stmt instanceof BreakStatement) { next.boundVariable = var; break; } } - if(t != Context.VOID && result.getBoolean()) + if (t != Context.VOID && result.getBoolean()) + { successCount++; + } next.boundVariable = var; } //revering scope ((AbstractListValue) rval).fatality(); c.setVariable("_", _val); c.setVariable("_i", _ite); - long promiseWontChange = successCount; + final long promiseWontChange = successCount; return (cc, tt) -> new NumericValue(promiseWontChange); }); @@ -363,32 +425,37 @@ public class Loops { expression.addLazyFunction("reduce", 3, (c, t, lv) -> { - Value rval= lv.get(0).evalValue(c, Context.NONE); - if (rval.isNull()) return ListValue.lazyEmpty(); - if (!(rval instanceof AbstractListValue)) + final Value rval = lv.get(0).evalValue(c, Context.NONE); + if (rval.isNull()) + { + return ListValue.lazyEmpty(); + } + if (!(rval instanceof final AbstractListValue alv)) + { throw new InternalExpressionException("First argument of 'reduce' should be a list or iterator"); - LazyValue expr = lv.get(1); + } + final LazyValue expr = lv.get(1); Value acc = lv.get(2).evalValue(c, Context.NONE); - Iterator iterator = ((AbstractListValue) rval).iterator(); + final Iterator iterator = alv.iterator(); if (!iterator.hasNext()) { - Value seriouslyWontChange = acc; + final Value seriouslyWontChange = acc; return (cc, tt) -> seriouslyWontChange; } //scoping - LazyValue _val = c.getVariable("_"); - LazyValue _acc = c.getVariable("_a"); - LazyValue _ite = c.getVariable("_i"); + final LazyValue _val = c.getVariable("_"); + final LazyValue _acc = c.getVariable("_a"); + final LazyValue _ite = c.getVariable("_i"); - for (int i=0; iterator.hasNext(); i++) + for (int i = 0; iterator.hasNext(); i++) { - Value next = iterator.next(); - String var = next.boundVariable; + final Value next = iterator.next(); + final String var = next.boundVariable; next.bindTo("_"); - Value promiseWontChangeYou = acc; - int seriously = i; + final Value promiseWontChangeYou = acc; + final int seriously = i; c.setVariable("_a", (cc, tt) -> promiseWontChangeYou.bindTo("_a")); c.setVariable("_", (cc, tt) -> next); c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i")); @@ -396,9 +463,12 @@ public class Loops { { acc = expr.evalValue(c, t); } - catch (BreakStatement | ContinueStatement stmt) + catch (final BreakStatement | ContinueStatement stmt) { - if (stmt.retval != null) acc = stmt.retval; + if (stmt.retval != null) + { + acc = stmt.retval; + } if (stmt instanceof BreakStatement) { next.boundVariable = var; @@ -413,7 +483,7 @@ public class Loops { c.setVariable("_", _val); c.setVariable("_i", _ite); - Value hopeItsEnoughPromise = acc; + final Value hopeItsEnoughPromise = acc; return (cc, tt) -> hopeItsEnoughPromise; }); } diff --git a/src/main/java/carpet/script/language/Operators.java b/src/main/java/carpet/script/language/Operators.java index a2c7a46b..539ed3fc 100644 --- a/src/main/java/carpet/script/language/Operators.java +++ b/src/main/java/carpet/script/language/Operators.java @@ -21,8 +21,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -public class Operators { - public static final Map precedence = new HashMap() {{ +public class Operators +{ + public static final Map precedence = new HashMap<>() + {{ put("attribute~:", 80); put("unary+-!...", 60); put("exponent^", 40); @@ -37,44 +39,68 @@ public class Operators { put("nextop;", 1); }}; - public static void apply(Expression expression) + public static void apply(final Expression expression) { expression.addBinaryOperator("+", precedence.get("addition+-"), true, Value::add); expression.addFunction("sum", lv -> { - int size = lv.size(); - if (size == 0) return Value.NULL; + final int size = lv.size(); + if (size == 0) + { + return Value.NULL; + } Value accumulator = lv.get(0); - for (Value v: lv.subList(1, size)) accumulator = accumulator.add(v); + for (final Value v : lv.subList(1, size)) + { + accumulator = accumulator.add(v); + } return accumulator; }); expression.addFunctionalEquivalence("+", "sum"); expression.addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract); expression.addFunction("difference", lv -> { - int size = lv.size(); - if (size == 0) return Value.NULL; + final int size = lv.size(); + if (size == 0) + { + return Value.NULL; + } Value accumulator = lv.get(0); - for (Value v: lv.subList(1, size)) accumulator = accumulator.subtract(v); + for (final Value v : lv.subList(1, size)) + { + accumulator = accumulator.subtract(v); + } return accumulator; }); expression.addFunctionalEquivalence("-", "difference"); expression.addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply); expression.addFunction("product", lv -> { - int size = lv.size(); - if (size == 0) return Value.NULL; + final int size = lv.size(); + if (size == 0) + { + return Value.NULL; + } Value accumulator = lv.get(0); - for (Value v: lv.subList(1, size)) accumulator = accumulator.multiply(v); + for (final Value v : lv.subList(1, size)) + { + accumulator = accumulator.multiply(v); + } return accumulator; }); expression.addFunctionalEquivalence("*", "product"); expression.addBinaryOperator("/", precedence.get("multiplication*/%"), true, Value::divide); expression.addFunction("quotient", lv -> { - int size = lv.size(); - if (size == 0) return Value.NULL; + final int size = lv.size(); + if (size == 0) + { + return Value.NULL; + } Value accumulator = lv.get(0); - for (Value v: lv.subList(1, size)) accumulator = accumulator.divide(v); + for (final Value v : lv.subList(1, size)) + { + accumulator = accumulator.divide(v); + } return accumulator; }); expression.addFunctionalEquivalence("/", "quotient"); @@ -85,51 +111,79 @@ public class Operators { new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble()))); expression.addFunction("bitwise_and", lv -> { - int size = lv.size(); - if (size == 0) return Value.NULL; + final int size = lv.size(); + if (size == 0) + { + return Value.NULL; + } long accumulator = NumericValue.asNumber(lv.get(0)).getLong(); - for (Value v: lv.subList(1, size)) accumulator = accumulator & NumericValue.asNumber(v).getLong(); + for (final Value v : lv.subList(1, size)) + { + accumulator = accumulator & NumericValue.asNumber(v).getLong(); + } return new NumericValue(accumulator); }); expression.addFunction("bitwise_xor", lv -> { - int size = lv.size(); - if (size == 0) return Value.NULL; + final int size = lv.size(); + if (size == 0) + { + return Value.NULL; + } long accumulator = NumericValue.asNumber(lv.get(0)).getLong(); - for (Value v: lv.subList(1, size)) accumulator = accumulator ^ NumericValue.asNumber(v).getLong(); + for (final Value v : lv.subList(1, size)) + { + accumulator = accumulator ^ NumericValue.asNumber(v).getLong(); + } return new NumericValue(accumulator); }); expression.addFunction("bitwise_or", lv -> { - int size = lv.size(); - if (size == 0) return Value.NULL; + final int size = lv.size(); + if (size == 0) + { + return Value.NULL; + } long accumulator = NumericValue.asNumber(lv.get(0)).getLong(); - for (Value v: lv.subList(1, size)) accumulator = accumulator | NumericValue.asNumber(v).getLong(); + for (final Value v : lv.subList(1, size)) + { + accumulator = accumulator | NumericValue.asNumber(v).getLong(); + } return new NumericValue(accumulator); }); // lazy cause RHS is only conditional expression.addLazyBinaryOperator("&&", precedence.get("and&&"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) -> { // todo check how is optimizations going - Value v1 = lv1.evalValue(c, Context.BOOLEAN); - if (!v1.getBoolean()) return (cc, tt) -> v1; - return lv2; + final Value v1 = lv1.evalValue(c, Context.BOOLEAN); + return v1.getBoolean() ? lv2 : ((cc, tt) -> v1); }); expression.addPureLazyFunction("and", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> { - int last = lv.size()-1; - if (last == -1) return LazyValue.TRUE; - for (LazyValue l: lv.subList(0, last)) + final int last = lv.size() - 1; + if (last == -1) { - Value val = l.evalValue(c, Context.Type.BOOLEAN); - if (val instanceof FunctionUnpackedArgumentsValue) + return LazyValue.TRUE; + } + for (final LazyValue l : lv.subList(0, last)) + { + final Value val = l.evalValue(c, Context.Type.BOOLEAN); + if (val instanceof final FunctionUnpackedArgumentsValue fuav) { - for (Value it : (FunctionUnpackedArgumentsValue) val) - if (!it.getBoolean()) return (cc, tt) -> it; + for (final Value it : fuav) + { + if (!it.getBoolean()) + { + return (cc, tt) -> it; + } + } } else { - if (!val.getBoolean()) return (cc, tt) -> val; + if (!val.getBoolean()) + { + return (cc, tt) -> val; + } } } return lv.get(last); @@ -139,25 +193,35 @@ public class Operators { // lazy cause RHS is only conditional expression.addLazyBinaryOperator("||", precedence.get("or||"), false, true, t -> Context.Type.BOOLEAN, (c, t, lv1, lv2) -> { - Value v1 = lv1.evalValue(c, Context.BOOLEAN); - if (v1.getBoolean()) return (cc, tt) -> v1; - return lv2; + final Value v1 = lv1.evalValue(c, Context.BOOLEAN); + return v1.getBoolean() ? ((cc, tt) -> v1) : lv2; }); expression.addPureLazyFunction("or", -1, t -> Context.Type.BOOLEAN, (c, t, lv) -> { - int last = lv.size()-1; - if (last == -1) return LazyValue.FALSE; - for (LazyValue l: lv.subList(0, last)) + final int last = lv.size() - 1; + if (last == -1) { - Value val = l.evalValue(c, Context.Type.BOOLEAN); - if (val instanceof FunctionUnpackedArgumentsValue) + return LazyValue.FALSE; + } + for (final LazyValue l : lv.subList(0, last)) + { + final Value val = l.evalValue(c, Context.Type.BOOLEAN); + if (val instanceof final FunctionUnpackedArgumentsValue fuav) { - for (Value it : (FunctionUnpackedArgumentsValue) val) - if (it.getBoolean()) return (cc, tt) -> it; + for (final Value it : fuav) + { + if (it.getBoolean()) + { + return (cc, tt) -> it; + } + } } else { - if (val.getBoolean()) return (cc, tt) -> val; + if (val.getBoolean()) + { + return (cc, tt) -> val; + } } } return lv.get(last); @@ -169,12 +233,18 @@ public class Operators { expression.addBinaryOperator(">", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) > 0)); expression.addFunction("decreasing", lv -> { - int size = lv.size(); - if (size < 2) return Value.TRUE; - Value prev = lv.get(0); - for (Value next: lv.subList(1, size)) + final int size = lv.size(); + if (size < 2) { - if (prev.compareTo(next) <= 0) return Value.FALSE; + return Value.TRUE; + } + Value prev = lv.get(0); + for (final Value next : lv.subList(1, size)) + { + if (prev.compareTo(next) <= 0) + { + return Value.FALSE; + } prev = next; } return Value.TRUE; @@ -184,12 +254,18 @@ public class Operators { expression.addBinaryOperator(">=", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) >= 0)); expression.addFunction("nonincreasing", lv -> { - int size = lv.size(); - if (size < 2) return Value.TRUE; - Value prev = lv.get(0); - for (Value next: lv.subList(1, size)) + final int size = lv.size(); + if (size < 2) { - if (prev.compareTo(next) < 0) return Value.FALSE; + return Value.TRUE; + } + Value prev = lv.get(0); + for (final Value next : lv.subList(1, size)) + { + if (prev.compareTo(next) < 0) + { + return Value.FALSE; + } prev = next; } return Value.TRUE; @@ -199,12 +275,18 @@ public class Operators { expression.addBinaryOperator("<", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) < 0)); expression.addFunction("increasing", lv -> { - int size = lv.size(); - if (size < 2) return Value.TRUE; - Value prev = lv.get(0); - for (Value next: lv.subList(1, size)) + final int size = lv.size(); + if (size < 2) { - if (prev.compareTo(next) >= 0) return Value.FALSE; + return Value.TRUE; + } + Value prev = lv.get(0); + for (final Value next : lv.subList(1, size)) + { + if (prev.compareTo(next) >= 0) + { + return Value.FALSE; + } prev = next; } return Value.TRUE; @@ -214,79 +296,84 @@ public class Operators { expression.addBinaryOperator("<=", precedence.get("compare>=><=<"), false, (v1, v2) -> BooleanValue.of(v1.compareTo(v2) <= 0)); expression.addFunction("nondecreasing", lv -> { - int size = lv.size(); - if (size < 2) return Value.TRUE; - Value prev = lv.get(0); - for (Value next: lv.subList(1, size)) + final int size = lv.size(); + if (size < 2) { - if (prev.compareTo(next) > 0) return Value.FALSE; + return Value.TRUE; + } + Value prev = lv.get(0); + for (final Value next : lv.subList(1, size)) + { + if (prev.compareTo(next) > 0) + { + return Value.FALSE; + } prev = next; } return Value.TRUE; }); expression.addFunctionalEquivalence("<=", "nondecreasing"); - - expression.addMathematicalBinaryIntFunction("bitwise_shift_left", (num, amount) -> { - return num << amount; - }); - expression.addMathematicalBinaryIntFunction("bitwise_shift_right", (num, amount) -> { - return num >> amount; - }); + expression.addMathematicalBinaryIntFunction("bitwise_shift_left", (num, amount) -> num << amount); + expression.addMathematicalBinaryIntFunction("bitwise_shift_right", (num, amount) -> num >> amount); expression.addMathematicalBinaryIntFunction("bitwise_roll_left", (num, num2) -> { - long amount = num2 % 64; - - long amountToRoll = 64 - amount; - long rolledBits = ((-1L) >> amountToRoll) << amountToRoll; - long rolledAmount = (num & rolledBits) >> amountToRoll; + final long amount = num2 % 64; + final long amountToRoll = 64 - amount; + final long rolledBits = ((-1L) >> amountToRoll) << amountToRoll; + final long rolledAmount = (num & rolledBits) >> amountToRoll; return num << amount | rolledAmount; }); expression.addMathematicalBinaryIntFunction("bitwise_roll_right", (num, num2) -> { - long amount = num2 % 64; - - long amountToRoll = 64 - amount; - long rolledBits = ((-1L) << amountToRoll) >> amountToRoll; - long rolledAmount = (num & rolledBits) << amountToRoll; + final long amount = num2 % 64; + final long amountToRoll = 64 - amount; + final long rolledBits = ((-1L) << amountToRoll) >> amountToRoll; + final long rolledAmount = (num & rolledBits) << amountToRoll; return num >> amount | rolledAmount; }); expression.addMathematicalUnaryIntFunction("bitwise_not", d -> { - long num = d.longValue(); - return num ^ (-1L); + final long num = (long) d; + return ~num; }); - expression.addMathematicalUnaryIntFunction("bitwise_popcount", d -> Long.valueOf(Long.bitCount(d.longValue()))); - + expression.addMathematicalUnaryIntFunction("bitwise_popcount", d -> (long) Long.bitCount((long)d)); expression.addMathematicalUnaryIntFunction("double_to_long_bits", Double::doubleToLongBits); - expression.addUnaryFunction("long_to_double_bits", v -> { - return new NumericValue(Double.longBitsToDouble(NumericValue.asNumber(v).getLong())); - }); - - + expression.addUnaryFunction("long_to_double_bits", v -> + new NumericValue(Double.longBitsToDouble(NumericValue.asNumber(v).getLong()))); expression.addBinaryOperator("==", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.TRUE : Value.FALSE); expression.addFunction("equal", lv -> { - int size = lv.size(); - if (size < 2) return Value.TRUE; - Value prev = lv.get(0); - for (Value next: lv.subList(1, size)) + final int size = lv.size(); + if (size < 2) { - if (!prev.equals(next)) return Value.FALSE; + return Value.TRUE; + } + Value prev = lv.get(0); + for (final Value next : lv.subList(1, size)) + { + if (!prev.equals(next)) + { + return Value.FALSE; + } prev = next; } return Value.TRUE; }); expression.addFunctionalEquivalence("==", "equal"); - - expression.addBinaryOperator("!=", precedence.get("equal==!="), false, (v1, v2) -> v1.equals(v2) ? Value.FALSE : Value.TRUE); expression.addFunction("unique", lv -> { - int size = lv.size(); - if (size < 2) return Value.TRUE; + final int size = lv.size(); + if (size < 2) + { + return Value.TRUE; + } // need to order them so same obejects will be next to each other. lv.sort(Comparator.comparingInt(Value::hashCode)); Value prev = lv.get(0); - for (Value next: lv.subList(1, size)) + for (final Value next : lv.subList(1, size)) { - if (prev.equals(next)) return Value.FALSE; + if (prev.equals(next)) + { + return Value.FALSE; + } prev = next; } return Value.TRUE; @@ -296,38 +383,52 @@ public class Operators { // lazy cause of assignment which is non-trivial expression.addLazyBinaryOperator("=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) -> { - Value v1 = lv1.evalValue(c, Context.LVALUE); - Value v2 = lv2.evalValue(c); - if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue) + final Value v1 = lv1.evalValue(c, Context.LVALUE); + final Value v2 = lv2.evalValue(c); + if (v1 instanceof final ListValue.ListConstructorValue lcv && v2 instanceof final ListValue list) { - List ll = ((ListValue)v1).getItems(); - List rl = ((ListValue)v2).getItems(); - if (ll.size() < rl.size()) throw new InternalExpressionException("Too many values to unpack"); - if (ll.size() > rl.size()) throw new InternalExpressionException("Too few values to unpack"); - for (Value v: ll) v.assertAssignable(); - Iterator li = ll.iterator(); - Iterator ri = rl.iterator(); - while(li.hasNext()) + final List ll = lcv.getItems(); + final List rl = list.getItems(); + if (ll.size() < rl.size()) { - String lname = li.next().getVariable(); - Value vval = ri.next().reboundedTo(lname); + throw new InternalExpressionException("Too many values to unpack"); + } + if (ll.size() > rl.size()) + { + throw new InternalExpressionException("Too few values to unpack"); + } + for (final Value v : ll) + { + v.assertAssignable(); + } + final Iterator li = ll.iterator(); + final Iterator ri = rl.iterator(); + while (li.hasNext()) + { + final String lname = li.next().getVariable(); + final Value vval = ri.next().reboundedTo(lname); expression.setAnyVariable(c, lname, (cc, tt) -> vval); } return (cc, tt) -> Value.TRUE; } - if (v1 instanceof LContainerValue) + if (v1 instanceof final LContainerValue lcv) { - ContainerValueInterface container = ((LContainerValue) v1).getContainer(); + final ContainerValueInterface container = lcv.container(); if (container == null) + { return (cc, tt) -> Value.NULL; - Value address = ((LContainerValue) v1).getAddress(); - if (!(container.put(address, v2))) return (cc, tt) -> Value.NULL; + } + final Value address = lcv.address(); + if (!(container.put(address, v2))) + { + return (cc, tt) -> Value.NULL; + } return (cc, tt) -> v2; } v1.assertAssignable(); - String varname = v1.getVariable(); - Value copy = v2.reboundedTo(varname); - LazyValue boundedLHS = (cc, tt) -> copy; + final String varname = v1.getVariable(); + final Value copy = v2.reboundedTo(varname); + final LazyValue boundedLHS = (cc, tt) -> copy; expression.setAnyVariable(c, varname, boundedLHS); return boundedLHS; }); @@ -335,35 +436,44 @@ public class Operators { // lazy due to assignment expression.addLazyBinaryOperator("+=", precedence.get("assign=<>"), false, false, t -> Context.Type.LVALUE, (c, t, lv1, lv2) -> { - Value v1 = lv1.evalValue(c, Context.LVALUE); - Value v2 = lv2.evalValue(c); - if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue) + final Value v1 = lv1.evalValue(c, Context.LVALUE); + final Value v2 = lv2.evalValue(c); + if (v1 instanceof final ListValue.ListConstructorValue lcv && v2 instanceof final ListValue list) { - List ll = ((ListValue)v1).getItems(); - List rl = ((ListValue)v2).getItems(); - if (ll.size() < rl.size()) throw new InternalExpressionException("Too many values to unpack"); - if (ll.size() > rl.size()) throw new InternalExpressionException("Too few values to unpack"); - for (Value v: ll) v.assertAssignable(); - Iterator li = ll.iterator(); - Iterator ri = rl.iterator(); - while(li.hasNext()) + final List ll = lcv.getItems(); + final List rl = list.getItems(); + if (ll.size() < rl.size()) { - Value lval = li.next(); - String lname = lval.getVariable(); - Value result = lval.add(ri.next()).bindTo(lname); + throw new InternalExpressionException("Too many values to unpack"); + } + if (ll.size() > rl.size()) + { + throw new InternalExpressionException("Too few values to unpack"); + } + for (final Value v : ll) + { + v.assertAssignable(); + } + final Iterator li = ll.iterator(); + final Iterator ri = rl.iterator(); + while (li.hasNext()) + { + final Value lval = li.next(); + final String lname = lval.getVariable(); + final Value result = lval.add(ri.next()).bindTo(lname); expression.setAnyVariable(c, lname, (cc, tt) -> result); } return (cc, tt) -> Value.TRUE; } - if (v1 instanceof LContainerValue) + if (v1 instanceof final LContainerValue lcv) { - ContainerValueInterface cvi = ((LContainerValue) v1).getContainer(); + final ContainerValueInterface cvi = lcv.container(); if (cvi == null) { throw new InternalExpressionException("Failed to resolve left hand side of the += operation"); } - Value key = ((LContainerValue) v1).getAddress(); - Value value = cvi.get(key); + final Value key = lcv.address(); + final Value value = cvi.get(key); if (value instanceof ListValue || value instanceof MapValue) { ((AbstractListValue) value).append(v2); @@ -371,22 +481,22 @@ public class Operators { } else { - Value res = value.add(v2); + final Value res = value.add(v2); cvi.put(key, res); return (cc, tt) -> res; } } v1.assertAssignable(); - String varname = v1.getVariable(); - LazyValue boundedLHS; + final String varname = v1.getVariable(); + final LazyValue boundedLHS; if (v1 instanceof ListValue || v1 instanceof MapValue) { ((AbstractListValue) v1).append(v2); - boundedLHS = (cc, tt)-> v1; + boundedLHS = (cc, tt) -> v1; } else { - Value result = v1.add(v2).bindTo(varname); + final Value result = v1.add(v2).bindTo(varname); boundedLHS = (cc, tt) -> result; } expression.setAnyVariable(c, varname, boundedLHS); @@ -395,22 +505,34 @@ public class Operators { expression.addBinaryContextOperator("<>", precedence.get("assign=<>"), false, false, false, (c, t, v1, v2) -> { - if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue.ListConstructorValue) + if (v1 instanceof final ListValue.ListConstructorValue lcv1 && v2 instanceof final ListValue.ListConstructorValue lcv2) { - List ll = ((ListValue)v1).getItems(); - List rl = ((ListValue)v2).getItems(); - if (ll.size() < rl.size()) throw new InternalExpressionException("Too many values to unpack"); - if (ll.size() > rl.size()) throw new InternalExpressionException("Too few values to unpack"); - for (Value v: ll) v.assertAssignable(); - for (Value v: rl) v.assertAssignable(); - Iterator li = ll.iterator(); - Iterator ri = rl.iterator(); - while(li.hasNext()) + final List ll = lcv1.getItems(); + final List rl = lcv2.getItems(); + if (ll.size() < rl.size()) { - Value lval = li.next(); - Value rval = ri.next(); - String lname = lval.getVariable(); - String rname = rval.getVariable(); + throw new InternalExpressionException("Too many values to unpack"); + } + if (ll.size() > rl.size()) + { + throw new InternalExpressionException("Too few values to unpack"); + } + for (final Value v : ll) + { + v.assertAssignable(); + } + for (final Value v : rl) + { + v.assertAssignable(); + } + final Iterator li = ll.iterator(); + final Iterator ri = rl.iterator(); + while (li.hasNext()) + { + final Value lval = li.next(); + final Value rval = ri.next(); + final String lname = lval.getVariable(); + final String rname = rval.getVariable(); lval.reboundedTo(rname); rval.reboundedTo(lname); expression.setAnyVariable(c, lname, (cc, tt) -> rval); @@ -420,36 +542,37 @@ public class Operators { } v1.assertAssignable(); v2.assertAssignable(); - String lvalvar = v1.getVariable(); - String rvalvar = v2.getVariable(); - Value lval = v2.reboundedTo(lvalvar); - Value rval = v1.reboundedTo(rvalvar); + final String lvalvar = v1.getVariable(); + final String rvalvar = v2.getVariable(); + final Value lval = v2.reboundedTo(lvalvar); + final Value rval = v1.reboundedTo(rvalvar); expression.setAnyVariable(c, lvalvar, (cc, tt) -> lval); expression.setAnyVariable(c, rvalvar, (cc, tt) -> rval); return lval; }); - expression.addUnaryOperator("-", false, v -> NumericValue.asNumber(v).opposite()); + expression.addUnaryOperator("-", false, v -> NumericValue.asNumber(v).opposite()); expression.addUnaryOperator("+", false, NumericValue::asNumber); // could be non-lazy, but who cares - its a small one. expression.addLazyUnaryOperator("!", precedence.get("unary+-!..."), false, true, x -> Context.Type.BOOLEAN, (c, t, lv) -> - lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt)-> Value.FALSE : (cc, tt) -> Value.TRUE + lv.evalValue(c, Context.BOOLEAN).getBoolean() ? (cc, tt) -> Value.FALSE : (cc, tt) -> Value.TRUE ); // might need context boolean // lazy because of typed evaluation of the argument - expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, true, t -> t== Context.Type.LOCALIZATION?Context.NONE:t, (c, t, lv) -> + expression.addLazyUnaryOperator("...", Operators.precedence.get("unary+-!..."), false, true, t -> t == Context.Type.LOCALIZATION ? Context.NONE : t, (c, t, lv) -> { if (t == Context.LOCALIZATION) + { return (cc, tt) -> new FunctionAnnotationValue(lv.evalValue(c), FunctionAnnotationValue.Type.VARARG); - - Value params = lv.evalValue(c, t); - if (!(params instanceof AbstractListValue)) + } + if (!(lv.evalValue(c, t) instanceof final AbstractListValue alv)) + { throw new InternalExpressionException("Unable to unpack a non-list"); - FunctionUnpackedArgumentsValue fuaval = new FunctionUnpackedArgumentsValue( ((AbstractListValue) params).unpack()); + } + final FunctionUnpackedArgumentsValue fuaval = new FunctionUnpackedArgumentsValue(alv.unpack()); return (cc, tt) -> fuaval; - //throw new InternalExpressionException("That functionality has not been implemented yet."); }); } diff --git a/src/main/java/carpet/script/language/Sys.java b/src/main/java/carpet/script/language/Sys.java index b9efebde..475aac72 100644 --- a/src/main/java/carpet/script/language/Sys.java +++ b/src/main/java/carpet/script/language/Sys.java @@ -3,7 +3,6 @@ package carpet.script.language; import carpet.script.Context; import carpet.script.Expression; import carpet.script.LazyValue; -import carpet.script.ScriptHost; import carpet.script.exception.InternalExpressionException; import carpet.script.utils.PerlinNoiseSampler; import carpet.script.utils.SimplexNoiseSampler; @@ -27,12 +26,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -public class Sys { +public class Sys +{ public static final Random randomizer = new Random(); // %[argument_index$][flags][width][.precision][t]conversion private static final Pattern formatPattern = Pattern.compile("%(\\d+\\$)?([-#+ 0,(<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"); - public static void apply(Expression expression) + public static void apply(final Expression expression) { expression.addUnaryFunction("hash_code", v -> new NumericValue(v.hashCode())); @@ -40,21 +40,23 @@ public class Sys { expression.addTypedContextFunction("bool", 1, Context.BOOLEAN, (c, t, lv) -> { - Value v = lv.get(0); + final Value v = lv.get(0); if (v instanceof StringValue) { - String str = v.getString().toLowerCase(Locale.ROOT); - if ("false".equals(str) || "null".equals(str)) return Value.FALSE; + final String str = v.getString().toLowerCase(Locale.ROOT); + if ("false".equals(str) || "null".equals(str)) + { + return Value.FALSE; + } } return BooleanValue.of(v.getBoolean()); }); expression.addUnaryFunction("number", v -> { - if (v instanceof NumericValue num) + if (v instanceof final NumericValue num) { - if (num.isInteger()) return new NumericValue(num.getLong()); - return new NumericValue(num.getDouble()); + return new NumericValue(num.isInteger() ? num.getLong() : num.getDouble()); } if (v instanceof ListValue || v instanceof MapValue) { @@ -64,7 +66,7 @@ public class Sys { { return new NumericValue(v.getString()); } - catch (NumberFormatException format) + catch (final NumberFormatException format) { return Value.NULL; } @@ -73,51 +75,65 @@ public class Sys { expression.addFunction("str", lv -> { if (lv.size() == 0) - throw new InternalExpressionException("'str' requires at least one argument"); - String format = lv.get(0).getString(); - if (lv.size() == 1) - return new StringValue(format); - int argIndex = 1; - if (lv.get(1) instanceof ListValue && lv.size() == 2) { - lv = ((ListValue) lv.get(1)).getItems(); + throw new InternalExpressionException("'str' requires at least one argument"); + } + final String format = lv.get(0).getString(); + if (lv.size() == 1) + { + return new StringValue(format); + } + int argIndex = 1; + if (lv.get(1) instanceof final ListValue list && lv.size() == 2) + { + lv = list.getItems(); argIndex = 0; } - List args = new ArrayList<>(); - Matcher m = formatPattern.matcher(format); + final List args = new ArrayList<>(); + final Matcher m = formatPattern.matcher(format); - for (int i = 0, len = format.length(); i < len; ) { - if (m.find(i)) { + for (int i = 0, len = format.length(); i < len; ) + { + if (m.find(i)) + { // Anything between the start of the string and the beginning // of the format specifier is either fixed text or contains // an invalid format string. // [[scarpet]] but we skip it and let the String.format fail - char fmt = m.group(6).toLowerCase().charAt(0); + final char fmt = m.group(6).toLowerCase().charAt(0); if (fmt == 's') { if (argIndex >= lv.size()) - throw new InternalExpressionException("Not enough arguments for "+m.group(0)); + { + throw new InternalExpressionException("Not enough arguments for " + m.group(0)); + } args.add(lv.get(argIndex).getString()); argIndex++; } else if (fmt == 'd' || fmt == 'o' || fmt == 'x') { if (argIndex >= lv.size()) - throw new InternalExpressionException("Not enough arguments for "+m.group(0)); + { + throw new InternalExpressionException("Not enough arguments for " + m.group(0)); + } args.add(lv.get(argIndex).readInteger()); argIndex++; } else if (fmt == 'a' || fmt == 'e' || fmt == 'f' || fmt == 'g') { if (argIndex >= lv.size()) - throw new InternalExpressionException("Not enough arguments for "+m.group(0)); + { + throw new InternalExpressionException("Not enough arguments for " + m.group(0)); + } args.add(lv.get(argIndex).readDoubleNumber()); argIndex++; } else if (fmt == 'b') { if (argIndex >= lv.size()) - throw new InternalExpressionException("Not enough arguments for "+m.group(0)); + { + throw new InternalExpressionException("Not enough arguments for " + m.group(0)); + } args.add(lv.get(argIndex).getBoolean()); argIndex++; } @@ -127,11 +143,13 @@ public class Sys { } else { - throw new InternalExpressionException("Format not supported: "+m.group(6)); + throw new InternalExpressionException("Format not supported: " + m.group(6)); } i = m.end(); - } else { + } + else + { // No more valid format specifiers. Check for possible invalid // format specifiers. // [[scarpet]] but we skip it and let the String.format fail @@ -142,9 +160,9 @@ public class Sys { { return new StringValue(String.format(Locale.ROOT, format, args.toArray())); } - catch (IllegalFormatException ife) + catch (final IllegalFormatException ife) { - throw new InternalExpressionException("Illegal string format: "+ife.getMessage()); + throw new InternalExpressionException("Illegal string format: " + ife.getMessage()); } }); @@ -156,32 +174,40 @@ public class Sys { expression.addFunction("replace", (lv) -> { - if (lv.size() != 3 && lv.size() !=2) + if (lv.size() != 3 && lv.size() != 2) + { throw new InternalExpressionException("'replace' expects string to read, pattern regex, and optional replacement string"); - String data = lv.get(0).getString(); - String regex = lv.get(1).getString(); + } + final String data = lv.get(0).getString(); + final String regex = lv.get(1).getString(); String replacement = ""; if (lv.size() == 3) + { replacement = lv.get(2).getString(); + } try { return new StringValue(data.replaceAll(regex, replacement)); } - catch (PatternSyntaxException pse) + catch (final PatternSyntaxException pse) { - throw new InternalExpressionException("Incorrect pattern for 'replace': "+pse.getMessage()); + throw new InternalExpressionException("Incorrect pattern for 'replace': " + pse.getMessage()); } }); expression.addFunction("replace_first", (lv) -> { - if (lv.size() != 3 && lv.size() !=2) + if (lv.size() != 3 && lv.size() != 2) + { throw new InternalExpressionException("'replace_first' expects string to read, pattern regex, and optional replacement string"); - String data = lv.get(0).getString(); - String regex = lv.get(1).getString(); + } + final String data = lv.get(0).getString(); + final String regex = lv.get(1).getString(); String replacement = ""; if (lv.size() == 3) + { replacement = lv.get(2).getString(); + } return new StringValue(data.replaceFirst(regex, replacement)); }); @@ -189,31 +215,36 @@ public class Sys { expression.addUnaryFunction("length", v -> new NumericValue(v.length())); expression.addContextFunction("rand", -1, (c, t, lv) -> { - int argsize = lv.size(); + final int argsize = lv.size(); Random randomizer = Sys.randomizer; if (argsize != 1 && argsize != 2) - throw new InternalExpressionException("'rand' takes one (range) or two arguments (range and seed)"); - if (argsize == 2) randomizer = c.host.getRandom(NumericValue.asNumber(lv.get(1)).getLong()); - Value argument = lv.get(0); - if (argument instanceof ListValue) { - List list = ((ListValue) argument).getItems(); + throw new InternalExpressionException("'rand' takes one (range) or two arguments (range and seed)"); + } + if (argsize == 2) + { + randomizer = c.host.getRandom(NumericValue.asNumber(lv.get(1)).getLong()); + } + final Value argument = lv.get(0); + if (argument instanceof final ListValue listValue) + { + final List list = listValue.getItems(); return list.get(randomizer.nextInt(list.size())); } - double value = NumericValue.asNumber(argument).getDouble()*randomizer.nextDouble(); - if (t == Context.BOOLEAN) - return BooleanValue.of(value >= 1.0D); - return new NumericValue(value); + final double value = NumericValue.asNumber(argument).getDouble() * randomizer.nextDouble(); + return t == Context.BOOLEAN ? BooleanValue.of(value >= 1.0D) : new NumericValue(value); }); expression.addContextFunction("reset_seed", 1, (c, t, lv) -> { - boolean gotIt = c.host.resetRandom(NumericValue.asNumber(lv.get(0)).getLong()); + final boolean gotIt = c.host.resetRandom(NumericValue.asNumber(lv.get(0)).getLong()); return BooleanValue.of(gotIt); }); expression.addFunction("perlin", lv -> { - PerlinNoiseSampler sampler; - Value x, y, z; + final PerlinNoiseSampler sampler; + final Value x; + Value y; + Value z; if (lv.size() >= 4) { @@ -227,36 +258,45 @@ public class Sys { sampler = PerlinNoiseSampler.instance; y = Value.NULL; z = Value.NULL; - if (lv.size() == 0 ) + if (lv.size() == 0) + { throw new InternalExpressionException("'perlin' requires at least one dimension to sample from"); + } x = NumericValue.asNumber(lv.get(0)); if (lv.size() > 1) { y = NumericValue.asNumber(lv.get(1)); if (lv.size() > 2) + { z = NumericValue.asNumber(lv.get(2)); + } } } - double result; + final double result; if (z.isNull()) - if (y.isNull()) - result = sampler.sample1d(NumericValue.asNumber(x).getDouble()); - else - result = sampler.sample2d(NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble()); + { + result = y.isNull() + ? sampler.sample1d(NumericValue.asNumber(x).getDouble()) + : sampler.sample2d(NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble()); + } else + { result = sampler.sample3d( NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble(), NumericValue.asNumber(z).getDouble()); + } return new NumericValue(result); }); expression.addFunction("simplex", lv -> { - SimplexNoiseSampler sampler; - Value x, y, z; + final SimplexNoiseSampler sampler; + final Value x; + final Value y; + Value z; if (lv.size() >= 4) { @@ -269,22 +309,30 @@ public class Sys { { sampler = SimplexNoiseSampler.instance; z = Value.NULL; - if (lv.size() < 2 ) + if (lv.size() < 2) + { throw new InternalExpressionException("'simplex' requires at least two dimensions to sample from"); + } x = NumericValue.asNumber(lv.get(0)); y = NumericValue.asNumber(lv.get(1)); if (lv.size() > 2) + { z = NumericValue.asNumber(lv.get(2)); + } } - double result; + final double result; if (z.isNull()) + { result = sampler.sample2d(NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble()); + } else + { result = sampler.sample3d( NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble(), NumericValue.asNumber(z).getDouble()); + } return new NumericValue(result); }); @@ -303,17 +351,23 @@ public class Sys { expression.addFunction("convert_date", lv -> { int argsize = lv.size(); - if (lv.size() == 0) throw new InternalExpressionException("'convert_date' requires at least one parameter"); - Value value = lv.get(0); + if (lv.size() == 0) + { + throw new InternalExpressionException("'convert_date' requires at least one parameter"); + } + final Value value = lv.get(0); if (argsize == 1 && !(value instanceof ListValue)) { - Calendar cal = new GregorianCalendar(Locale.ROOT); + final Calendar cal = new GregorianCalendar(Locale.ROOT); cal.setTimeInMillis(NumericValue.asNumber(value, "timestamp").getLong()); - int weekday = cal.get(Calendar.DAY_OF_WEEK)-1; - if (weekday == 0) weekday = 7; + int weekday = cal.get(Calendar.DAY_OF_WEEK) - 1; + if (weekday == 0) + { + weekday = 7; + } return ListValue.ofNums( cal.get(Calendar.YEAR), - cal.get(Calendar.MONTH)+1, + cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), @@ -323,18 +377,18 @@ public class Sys { cal.get(Calendar.WEEK_OF_YEAR) ); } - else if(value instanceof ListValue) + else if (value instanceof final ListValue list) { - lv = ((ListValue) value).getItems(); + lv = list.getItems(); argsize = lv.size(); } - Calendar cal = new GregorianCalendar(0, 0, 0, 0, 0, 0); + final Calendar cal = new GregorianCalendar(0, 0, 0, 0, 0, 0); if (argsize == 3) { cal.set( NumericValue.asNumber(lv.get(0)).getInt(), - NumericValue.asNumber(lv.get(1)).getInt()-1, + NumericValue.asNumber(lv.get(1)).getInt() - 1, NumericValue.asNumber(lv.get(2)).getInt() ); } @@ -342,29 +396,32 @@ public class Sys { { cal.set( NumericValue.asNumber(lv.get(0)).getInt(), - NumericValue.asNumber(lv.get(1)).getInt()-1, + NumericValue.asNumber(lv.get(1)).getInt() - 1, NumericValue.asNumber(lv.get(2)).getInt(), NumericValue.asNumber(lv.get(3)).getInt(), NumericValue.asNumber(lv.get(4)).getInt(), NumericValue.asNumber(lv.get(5)).getInt() ); } - else throw new InternalExpressionException("Date conversion requires 3 arguments for Dates or 6 arguments, for time"); + else + { + throw new InternalExpressionException("Date conversion requires 3 arguments for Dates or 6 arguments, for time"); + } return new NumericValue(cal.getTimeInMillis()); }); // lazy cause evaluates expression multiple times expression.addLazyFunction("profile_expr", 1, (c, t, lv) -> { - LazyValue lazy = lv.get(0); - long end = System.nanoTime()+50000000L; + final LazyValue lazy = lv.get(0); + final long end = System.nanoTime() + 50000000L; long it = 0; - while (System.nanoTime() res; }); @@ -373,16 +430,18 @@ public class Sys { expression.addContextFunction("undef", 1, (c, t, lv) -> { - Value remove = lv.get(0); + final Value remove = lv.get(0); if (remove instanceof FunctionValue) { c.host.delFunction(expression.module, remove.getString()); return Value.NULL; } String varname = remove.getString(); - boolean isPrefix = varname.endsWith("*"); + final boolean isPrefix = varname.endsWith("*"); if (isPrefix) + { varname = varname.replaceAll("\\*+$", ""); + } if (isPrefix) { c.host.delFunctionWithPrefix(expression.module, varname); @@ -413,8 +472,8 @@ public class Sys { //deprecate expression.addContextFunction("vars", 1, (c, t, lv) -> { - String prefix = lv.get(0).getString(); - List values = new ArrayList<>(); + final String prefix = lv.get(0).getString(); + final List values = new ArrayList<>(); if (prefix.startsWith("global")) { c.host.globalVariableNames(expression.module, (s) -> s.startsWith(prefix)).forEach(s -> values.add(new StringValue(s))); @@ -429,19 +488,23 @@ public class Sys { // lazy cause default expression may not be executed if not needed expression.addLazyFunction("system_variable_get", (c, t, lv) -> { - if (lv.size() == 0) throw new InternalExpressionException("'system_variable_get' expects at least a key to be fetched"); - Value key = lv.get(0).evalValue(c); - if (lv.size() > 1) c.host.scriptServer().systemGlobals.computeIfAbsent(key, k -> lv.get(1).evalValue(c)); - Value res = c.host.scriptServer().systemGlobals.get(key); - if (res!=null) return (cc, tt) -> res; - return LazyValue.NULL; + if (lv.size() == 0) + { + throw new InternalExpressionException("'system_variable_get' expects at least a key to be fetched"); + } + final Value key = lv.get(0).evalValue(c); + if (lv.size() > 1) + { + c.host.scriptServer().systemGlobals.computeIfAbsent(key, k -> lv.get(1).evalValue(c)); + } + final Value res = c.host.scriptServer().systemGlobals.get(key); + return res == null ? LazyValue.NULL : ((cc, tt) -> res); }); expression.addContextFunction("system_variable_set", 2, (c, t, lv) -> { - Value res = c.host.scriptServer().systemGlobals.put(lv.get(0), lv.get(1)); - if (res!=null) return res; - return Value.NULL; + final Value res = c.host.scriptServer().systemGlobals.put(lv.get(0), lv.get(1)); + return res == null ? Value.NULL : res; }); } } diff --git a/src/main/java/carpet/script/language/Threading.java b/src/main/java/carpet/script/language/Threading.java index 52f3c1a5..b61448d6 100644 --- a/src/main/java/carpet/script/language/Threading.java +++ b/src/main/java/carpet/script/language/Threading.java @@ -11,14 +11,16 @@ import carpet.script.value.Value; public class Threading { - public static void apply(Expression expression) + public static void apply(final Expression expression) { expression.addFunctionWithDelegation("task", -1, false, false, (c, t, expr, tok, lv) -> { if (lv.size() == 0) + { throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); - ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); + } + final FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 0, false, true); + final ThreadValue thread = new ThreadValue(Value.NULL, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); Thread.yield(); return thread; }); @@ -26,30 +28,36 @@ public class Threading expression.addFunctionWithDelegation("task_thread", -1, false, false, (c, t, expr, tok, lv) -> { if (lv.size() < 2) + { throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - Value queue = lv.get(0); - FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); - ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); + } + final Value queue = lv.get(0); + final FunctionArgument functionArgument = FunctionArgument.findIn(c, expression.module, lv, 1, false, true); + final ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.checkedArgs()); Thread.yield(); return thread; }); expression.addContextFunction("task_count", -1, (c, t, lv) -> - (lv.size() > 0)? new NumericValue(c.host.taskCount(lv.get(0))):new NumericValue(c.host.taskCount())); + (lv.size() > 0) ? new NumericValue(c.host.taskCount(lv.get(0))) : new NumericValue(c.host.taskCount())); expression.addUnaryFunction("task_value", (v) -> { - if (!(v instanceof ThreadValue)) + if (!(v instanceof final ThreadValue tv)) + { throw new InternalExpressionException("'task_value' could only be used with a task value"); - return ((ThreadValue) v).getValue(); + } + return tv.getValue(); }); expression.addUnaryFunction("task_join", (v) -> { - if (!(v instanceof ThreadValue)) + if (!(v instanceof final ThreadValue tv)) + { throw new InternalExpressionException("'task_join' could only be used with a task value"); - return ((ThreadValue) v).join(); + } + return tv.join(); }); expression.addLazyFunction("task_dock", 1, (c, t, lv) -> @@ -61,15 +69,20 @@ public class Threading expression.addUnaryFunction("task_completed", (v) -> { - if (!(v instanceof ThreadValue)) + if (!(v instanceof final ThreadValue tv)) + { throw new InternalExpressionException("'task_completed' could only be used with a task value"); - return BooleanValue.of(((ThreadValue) v).isFinished()); + } + return BooleanValue.of(tv.isFinished()); }); // lazy cause expr is evaluated in the same type expression.addLazyFunction("synchronize", (c, t, lv) -> { - if (lv.size() == 0) throw new InternalExpressionException("'synchronize' require at least an expression to synchronize"); + if (lv.size() == 0) + { + throw new InternalExpressionException("'synchronize' require at least an expression to synchronize"); + } Value lockValue = Value.NULL; int ind = 0; if (lv.size() == 2) @@ -79,7 +92,7 @@ public class Threading } synchronized (c.host.getLock(lockValue)) { - Value ret = lv.get(ind).evalValue(c, t); + final Value ret = lv.get(ind).evalValue(c, t); return (_c, _t) -> ret; } }); @@ -87,15 +100,21 @@ public class Threading // lazy since exception expression is very conditional expression.addLazyFunction("sleep", (c, t, lv) -> { - long time = lv.isEmpty()?0L:NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); + final long time = lv.isEmpty() ? 0L : NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); boolean interrupted = false; try { - if (Thread.interrupted()) interrupted = true; - if (time > 0) Thread.sleep(time); + if (Thread.interrupted()) + { + interrupted = true; + } + if (time > 0) + { + Thread.sleep(time); + } Thread.yield(); } - catch (InterruptedException ignored) + catch (final InterruptedException ignored) { interrupted = true; } diff --git a/src/main/java/carpet/script/utils/AppStoreManager.java b/src/main/java/carpet/script/utils/AppStoreManager.java index 2b410247..1f331476 100644 --- a/src/main/java/carpet/script/utils/AppStoreManager.java +++ b/src/main/java/carpet/script/utils/AppStoreManager.java @@ -18,6 +18,7 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.commands.CommandRuntimeException; import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.level.storage.LevelResource; + import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; @@ -40,22 +41,28 @@ import org.apache.commons.io.IOUtils; */ public class AppStoreManager { - /** A local copy of the scarpet repo's file structure, to avoid multiple queries to github.com while typing out the + /** + * A local copy of the scarpet repo's file structure, to avoid multiple queries to github.com while typing out the * {@code /script download} command and getting the suggestions. */ private static StoreNode APP_STORE_ROOT = StoreNode.folder(null, ""); - /** This is the base link to the scarpet app repo from the github api. + /** + * This is the base link to the scarpet app repo from the github api. */ private static String scarpetRepoLink = "https://api.github.com/repos/gnembon/scarpet/contents/programs/"; - private static record AppInfo(String name, String url, StoreNode source) {} + private record AppInfo(String name, String url, StoreNode source) + { + } public static class ScarpetAppStoreValidator extends Validator { - @Override public String validate(CommandSourceStack source, CarpetRule currentRule, String newValue, String stringInput) + @Override + public String validate(final CommandSourceStack source, final CarpetRule currentRule, String newValue, final String stringInput) { - if (newValue.equals(currentRule.value())) { + if (newValue.equals(currentRule.value())) + { // Don't refresh the local repo if it's the same (world change), helps preventing hitting rate limits from github when // getting suggestions. Pending is a way to invalidate the cache when it gets old, and investigating api usage further return newValue; @@ -66,12 +73,19 @@ public class AppStoreManager scarpetRepoLink = null; return newValue; } - if (newValue.endsWith("/")) newValue = newValue.replaceAll("/$", ""); - scarpetRepoLink = "https://api.github.com/repos/"+newValue+"/"; + if (newValue.endsWith("/")) + { + newValue = newValue.replaceAll("/$", ""); + } + scarpetRepoLink = "https://api.github.com/repos/" + newValue + "/"; return newValue; } + @Override - public String description() { return "Appstore link should point to a valid github repository";} + public String description() + { + return "Appstore link should point to a valid github repository"; + } } public static class StoreNode @@ -81,18 +95,19 @@ public class AppStoreManager public Map children; public boolean sealed; public String value; - public static StoreNode folder(StoreNode parent, String name) + + public static StoreNode folder(final StoreNode parent, final String name) { - StoreNode node = new StoreNode(parent, name); + final StoreNode node = new StoreNode(parent, name); node.children = new HashMap<>(); node.value = null; node.sealed = false; return node; } - public static StoreNode scriptFile(StoreNode parent, String name, String value) + public static StoreNode scriptFile(final StoreNode parent, final String name, final String value) { - StoreNode node = new StoreNode(parent, name); + final StoreNode node = new StoreNode(parent, name); node.children = null; node.value = value; node.sealed = true; @@ -103,19 +118,23 @@ public class AppStoreManager { return value != null; } + public String pathElement() { - return name+(isLeaf()?"":"/"); + return name + (isLeaf() ? "" : "/"); } + public String getPath() { return createPrePath().toString(); } + private StringBuilder createPrePath() { return this == APP_STORE_ROOT ? new StringBuilder() : parent.createPrePath().append(pathElement()); } - private StoreNode(StoreNode parent, String name) + + private StoreNode(final StoreNode parent, final String name) { this.parent = parent; this.name = name; @@ -124,32 +143,38 @@ public class AppStoreManager public synchronized void fillChildren() throws IOException { - if (sealed) return; - if (scarpetRepoLink == null) throw new IOException("Accessing scarpet app repo is disabled"); + if (sealed) + { + return; + } + if (scarpetRepoLink == null) + { + throw new IOException("Accessing scarpet app repo is disabled"); + } - String queryPath = scarpetRepoLink + getPath(); - String response; + final String queryPath = scarpetRepoLink + getPath(); + final String response; try { response = IOUtils.toString(new URL(queryPath), StandardCharsets.UTF_8); } - catch (IOException e) + catch (final IOException e) { // Not sealing to allow retrying throw new IOException("Problems fetching " + queryPath, e); } - JsonArray files = JsonParser.parseString(response).getAsJsonArray(); - for(JsonElement je : files) + final JsonArray files = JsonParser.parseString(response).getAsJsonArray(); + for (final JsonElement je : files) { - JsonObject jo = je.getAsJsonObject(); - String name = jo.get("name").getAsString(); + final JsonObject jo = je.getAsJsonObject(); + final String name = jo.get("name").getAsString(); if (jo.get("type").getAsString().equals("dir")) { children.put(name, folder(this, name)); } else// if (name.matches("(\\w+\\.scl?)")) { - String value = jo.get("download_url").getAsString(); + final String value = jo.get("download_url").getAsString(); children.put(name, scriptFile(this, name, value)); } } @@ -159,12 +184,16 @@ public class AppStoreManager /** * Returns true if doing down the directory structire cannot continue since the matching element is either a leaf or * a string not matching of any node. + * * @param pathElement * @return */ - public boolean cannotContinueFor(String pathElement) throws IOException + public boolean cannotContinueFor(final String pathElement) throws IOException { - if (isLeaf()) return true; + if (isLeaf()) + { + return true; + } fillChildren(); return !children.containsKey(pathElement); } @@ -173,120 +202,140 @@ public class AppStoreManager { if (isLeaf()) { - if (name.endsWith(".sc")) - return Collections.singletonList(getPath()); - return Collections.emptyList(); + return name.endsWith(".sc") ? Collections.singletonList(getPath()) : Collections.emptyList(); } fillChildren(); - String prefix = getPath(); + final String prefix = getPath(); return children.values().stream(). filter(n -> (!n.isLeaf() || n.name.endsWith(".sc"))). - map(s -> prefix+s.pathElement().replaceAll("/$", "")). + map(s -> prefix + s.pathElement().replaceAll("/$", "")). collect(Collectors.toList()); } - public StoreNode drillDown(String pathElement) throws IOException + public StoreNode drillDown(final String pathElement) throws IOException { - if (isLeaf()) throw new IOException(pathElement+" is not a folder"); + if (isLeaf()) + { + throw new IOException(pathElement + " is not a folder"); + } fillChildren(); - if (!children.containsKey(pathElement)) throw new IOException("Folder "+pathElement+" is not present"); + if (!children.containsKey(pathElement)) + { + throw new IOException("Folder " + pathElement + " is not present"); + } return children.get(pathElement); } - public String getValue(String file) throws IOException + public String getValue(final String file) throws IOException { - StoreNode leaf = drillDown(file); - if (!leaf.isLeaf()) throw new IOException(file+" is not a file"); + final StoreNode leaf = drillDown(file); + if (!leaf.isLeaf()) + { + throw new IOException(file + " is not a file"); + } return leaf.value; } } - /** This method searches for valid file names from the user-inputted string, e.g if the user has thus far typed + /** + * This method searches for valid file names from the user-inputted string, e.g if the user has thus far typed * {@code survival/a} then it will return all the files in the {@code survival} directory of the scarpet repo (and * will automatically highlight those starting with a), and the string {@code survival/} as the current most valid path. * * @param currentPath The path down which we want to search for files * @return A pair of the current valid path, as well as the set of all the file/directory names at the end of that path */ - public static List suggestionsFromPath(String currentPath) throws IOException + public static List suggestionsFromPath(final String currentPath) throws IOException { - String[] path = currentPath.split("/"); + final String[] path = currentPath.split("/"); StoreNode appKiosk = APP_STORE_ROOT; - for(String pathElement : path) + for (final String pathElement : path) { - if (appKiosk.cannotContinueFor(pathElement)) break; + if (appKiosk.cannotContinueFor(pathElement)) + { + break; + } appKiosk = appKiosk.children.get(pathElement); } - List filteredSuggestions = appKiosk.createPathSuggestions().stream().filter(s -> s.startsWith(currentPath)).collect(Collectors.toList()); - if (filteredSuggestions.size() == 1) { + final List filteredSuggestions = appKiosk.createPathSuggestions().stream().filter(s -> s.startsWith(currentPath)).collect(Collectors.toList()); + if (filteredSuggestions.size() == 1) + { if (!appKiosk.isLeaf()) + { return suggestionsFromPath(filteredSuggestions.get(0)); // Start suggesting directory contents + } } return filteredSuggestions; } - - /** Downloads script and saves it to appropriate place. + /** + * Downloads script and saves it to appropriate place. * * @param path The user-inputted path to the script * @return {@code 1} if we succesfully saved the script, {@code 0} otherwise */ - public static int downloadScript(CommandSourceStack source, String path) + public static int downloadScript(final CommandSourceStack source, final String path) { - AppInfo nodeInfo = getFileNode(path); + final AppInfo nodeInfo = getFileNode(path); return downloadScript(source, path, nodeInfo, false); } - private static int downloadScript(CommandSourceStack source, String path, AppInfo nodeInfo, boolean useTrash) + private static int downloadScript(final CommandSourceStack source, final String path, final AppInfo nodeInfo, final boolean useTrash) { - String code; + final String code; try { code = IOUtils.toString(new URL(nodeInfo.url()), StandardCharsets.UTF_8); } - catch (IOException e) + catch (final IOException e) { - throw new CommandRuntimeException(Messenger.c("rb Failed to obtain app file content: "+e.getMessage())); + throw new CommandRuntimeException(Messenger.c("rb Failed to obtain app file content: " + e.getMessage())); } - if (!saveScriptToFile(source, path, nodeInfo.name(), code, false, useTrash)) return 0; - boolean success = CarpetServer.scriptServer.addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source()); - return success?1:0; + if (!saveScriptToFile(source, path, nodeInfo.name(), code, false, useTrash)) + { + return 0; + } + final boolean success = CarpetServer.scriptServer.addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source()); + return success ? 1 : 0; } - /** Gets the code once the user inputs the command. + /** + * Gets the code once the user inputs the command. * * @param appPath The user inputted path to the scarpet script * @return Pair of app file name and content */ - public static AppInfo getFileNode(String appPath) + public static AppInfo getFileNode(final String appPath) { return getFileNodeFrom(APP_STORE_ROOT, appPath); } - public static AppInfo getFileNodeFrom(StoreNode start, String appPath) + public static AppInfo getFileNodeFrom(final StoreNode start, final String appPath) { - String[] path = appPath.split("/"); + final String[] path = appPath.split("/"); StoreNode appKiosk = start; try { - for(String pathElement : Arrays.copyOfRange(path, 0, path.length-1)) + for (final String pathElement : Arrays.copyOfRange(path, 0, path.length - 1)) + { appKiosk = appKiosk.drillDown(pathElement); - String appName = path[path.length-1]; + } + final String appName = path[path.length - 1]; appKiosk.getValue(appName); return new AppInfo(appName, appKiosk.getValue(appName), appKiosk); } - catch (IOException e) + catch (final IOException e) { - throw new CommandRuntimeException(Messenger.c("rb '"+ appPath + "' is not a valid path to a scarpet app: "+e.getMessage())); + throw new CommandRuntimeException(Messenger.c("rb '" + appPath + "' is not a valid path to a scarpet app: " + e.getMessage())); } } - public static boolean saveScriptToFile(CommandSourceStack source, String path, String appFileName, String code, boolean globalSavePath, boolean useTrash) + public static boolean saveScriptToFile(final CommandSourceStack source, final String path, final String appFileName, final String code, final boolean globalSavePath, final boolean useTrash) { - Path scriptLocation; + final Path scriptLocation; if (globalSavePath && !source.getServer().isDedicatedServer()) // never happens, this is always called with globalSavePath being false { //cos config folder only is in clients scriptLocation = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts/appstore").toAbsolutePath().resolve(path); @@ -307,29 +356,29 @@ public class AppStoreManager int i = 0; while (Files.exists(trashPath)) { - String[] nameAndExtension = appFileName.split("\\."); - String newFileName = String.format(nameAndExtension[0] + "%02d." + nameAndExtension[1],i); + final String[] nameAndExtension = appFileName.split("\\."); + final String newFileName = String.format(nameAndExtension[0] + "%02d." + nameAndExtension[1], i); trashPath = trashPath.getParent().resolve(newFileName); i++; } Files.move(scriptLocation, trashPath); } - Messenger.m(source, String.format("gi Note: replaced existing app '%s'"+(useTrash ? " (old moved to /trash folder)" : ""), appFileName)); + Messenger.m(source, String.format("gi Note: replaced existing app '%s'" + (useTrash ? " (old moved to /trash folder)" : ""), appFileName)); } - BufferedWriter writer = Files.newBufferedWriter(scriptLocation); + final BufferedWriter writer = Files.newBufferedWriter(scriptLocation); writer.write(code); writer.close(); } - catch (IOException e) + catch (final IOException e) { - Messenger.m(source, "r Error while downloading app: " + e.toString()); + Messenger.m(source, "r Error while downloading app: " + e); CarpetScriptServer.LOG.warn("Error while downloading app", e); return false; } return true; } - public static void writeUrlToFile(String url, Path destination) throws IOException + public static void writeUrlToFile(final String url, final Path destination) throws IOException { try (final InputStream in = new URL(url).openStream()) { @@ -337,88 +386,112 @@ public class AppStoreManager } } - private static String getFullContentUrl(String original, StoreNode storeSource) + private static String getFullContentUrl(final String original, final StoreNode storeSource) { if (original.matches("^https?://.*$")) // We've got a full url here: Just use it + { return original; + } if (original.charAt(0) == '/') // We've got an absolute path: Use app store root + { return getFileNode(original.substring(1)).url(); + } return getFileNodeFrom(storeSource, original).url(); // Relative path: Use download location } - public static void addResource(CarpetScriptHost carpetScriptHost, StoreNode storeSource, Value resource) + public static void addResource(final CarpetScriptHost carpetScriptHost, final StoreNode storeSource, final Value resource) { - if (!(resource instanceof MapValue)) - throw new InternalExpressionException("This is not a valid resource map: "+resource.getString()); - Map resourceMap = ((MapValue) resource).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue)); - if (!resourceMap.containsKey("source")) throw new InternalExpressionException("Missing 'source' field in resource descriptor: "+resource.getString()); - String source = resourceMap.get("source").getString(); - String contentUrl = getFullContentUrl(source, storeSource); - String target = resourceMap.computeIfAbsent("target", k -> new StringValue(contentUrl.substring(contentUrl.lastIndexOf('/') + 1))).getString(); - boolean shared = resourceMap.getOrDefault("shared", Value.FALSE).getBoolean(); + if (!(resource instanceof final MapValue map)) + { + throw new InternalExpressionException("This is not a valid resource map: " + resource.getString()); + } + final Map resourceMap = map.getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue)); + if (!resourceMap.containsKey("source")) + { + throw new InternalExpressionException("Missing 'source' field in resource descriptor: " + resource.getString()); + } + final String source = resourceMap.get("source").getString(); + final String contentUrl = getFullContentUrl(source, storeSource); + final String target = resourceMap.computeIfAbsent("target", k -> new StringValue(contentUrl.substring(contentUrl.lastIndexOf('/') + 1))).getString(); + final boolean shared = resourceMap.getOrDefault("shared", Value.FALSE).getBoolean(); if (!carpetScriptHost.applyActionForResource(target, shared, p -> { - try { + try + { writeUrlToFile(contentUrl, p); - } catch (IOException e) { - throw new InternalExpressionException("Unable to write resource "+target+": "+e.toString()); + } + catch (final IOException e) + { + throw new InternalExpressionException("Unable to write resource " + target + ": " + e); } })) { - throw new InternalExpressionException("Unable to write resource "+target); + throw new InternalExpressionException("Unable to write resource " + target); } - CarpetScriptServer.LOG.info("Downloaded resource "+target+" from "+contentUrl); + CarpetScriptServer.LOG.info("Downloaded resource " + target + " from " + contentUrl); } /** * Gets a new StoreNode for an app's dependency with proper relativeness. Will be null if it comes from an external URL + * * @param originalSource The StoreNode from the container's app - * @param sourceString The string the app specified as source - * @param contentUrl The full content URL, from {@link #getFullContentUrl(String, StoreNode)} + * @param sourceString The string the app specified as source + * @param contentUrl The full content URL, from {@link #getFullContentUrl(String, StoreNode)} * @return A {@link StoreNode} that can be used in an app that came from the provided source */ - private static StoreNode getNewStoreNode(StoreNode originalSource, String sourceString, String contentUrl) + private static StoreNode getNewStoreNode(final StoreNode originalSource, String sourceString, final String contentUrl) { StoreNode next = originalSource; if (sourceString == contentUrl) // External URL (check getFullUrlContent) + { return null; + } if (sourceString.charAt(0) == '/') // Absolute URL { next = APP_STORE_ROOT; sourceString = sourceString.substring(1); } - String[] dirs = sourceString.split("/"); + final String[] dirs = sourceString.split("/"); try { for (int i = 0; i < dirs.length - 1; i++) + { next = next.drillDown(dirs[i]); + } } - catch (IOException e) + catch (final IOException e) { return null; // Should never happen, but let's not give a potentially incorrect node just in case } return next; } - public static void addLibrary(CarpetScriptHost carpetScriptHost, StoreNode storeSource, Value library) { - if (!(library instanceof MapValue)) - throw new InternalExpressionException("This is not a valid library map: "+library.getString()); - Map libraryMap = ((MapValue) library).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), e -> e.getValue().getString())); - String source = libraryMap.get("source"); - String contentUrl = getFullContentUrl(source, storeSource); - String target = libraryMap.computeIfAbsent("target", k -> contentUrl.substring(contentUrl.lastIndexOf('/') + 1)); + public static void addLibrary(final CarpetScriptHost carpetScriptHost, final StoreNode storeSource, final Value library) + { + if (!(library instanceof final MapValue map)) + { + throw new InternalExpressionException("This is not a valid library map: " + library.getString()); + } + final Map libraryMap = map.getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), e -> e.getValue().getString())); + final String source = libraryMap.get("source"); + final String contentUrl = getFullContentUrl(source, storeSource); + final String target = libraryMap.computeIfAbsent("target", k -> contentUrl.substring(contentUrl.lastIndexOf('/') + 1)); if (!(contentUrl.endsWith(".sc") || contentUrl.endsWith(".scl"))) + { throw new InternalExpressionException("App resource type must download a scarpet app or library."); + } if (target.indexOf('/') != -1) + { throw new InternalExpressionException("App resource tried to leave script reserved space"); + } try { downloadScript(carpetScriptHost.responsibleSource, target, new AppInfo(target, contentUrl, getNewStoreNode(storeSource, source, contentUrl)), true); } - catch (CommandRuntimeException e) + catch (final CommandRuntimeException e) { - throw new InternalExpressionException("Error when installing app dependencies: " + e.toString()); + throw new InternalExpressionException("Error when installing app dependencies: " + e); } - CarpetScriptServer.LOG.info("Downloaded app "+target+" from "+contentUrl); + CarpetScriptServer.LOG.info("Downloaded app " + target + " from " + contentUrl); } } diff --git a/src/main/java/carpet/script/utils/BiomeInfo.java b/src/main/java/carpet/script/utils/BiomeInfo.java index f36054a1..5870848c 100644 --- a/src/main/java/carpet/script/utils/BiomeInfo.java +++ b/src/main/java/carpet/script/utils/BiomeInfo.java @@ -6,6 +6,7 @@ import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; import carpet.script.value.ValueConversions; + import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -20,12 +21,9 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; public class BiomeInfo { - public final static Map> biomeFeatures = new HashMap>(){{ - //put("top_material", (w, b) -> new BlockValue( b.getGenerationSettings(). getSurfaceConfig().getTopMaterial(), null, null)); - //put("under_material", (w, b) -> new BlockValue( b.getGenerationSettings().getSurfaceConfig().getUnderMaterial(), null, null)); - //put("category", (w, b) -> StringValue.of(Biome.getBiomeCategory(Holder.direct(b)).getName())); + public static final Map> biomeFeatures = new HashMap<>() + {{ put("tags", (w, b) -> ListValue.wrap(w.registryAccess().registryOrThrow(Registries.BIOME).getTags().filter(p -> p.getSecond().stream().anyMatch(h -> h.value() == b)).map(p -> p.getFirst().location()).map(ValueConversions::of))); - put("temperature", (w, b) -> NumericValue.of(b.getBaseTemperature())); put("fog_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getFogColor())); put("foliage_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getFoliageColorOverride().orElse(4764952))); // client Biome.getDefaultFoliageColor @@ -34,11 +32,8 @@ public class BiomeInfo put("water_fog_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getWaterFogColor())); put("humidity", (w, b) -> NumericValue.of(((BiomeInterface) (Object) b).getClimateSettings().downfall())); put("precipitation", (w, b) -> StringValue.of(b.getPrecipitationAt(new BlockPos(0, w.getSeaLevel(), 0)).name().toLowerCase(Locale.ROOT))); - //put("depth", (w, b) -> NumericValue.of(b.getDepth())); - //put("scale", (w, b) -> NumericValue.of(b.getScale())); put("features", (w, b) -> { - - Registry> registry = w.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE); + final Registry> registry = w.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE); return ListValue.wrap( b.getGenerationSettings().features().stream().map(step -> ListValue.wrap(step.stream().map(cfp -> @@ -47,9 +42,5 @@ public class BiomeInfo ) ); }); - //put("structures", (w, b) -> { - // Registry> registry = w.getRegistryManager().get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY); - // return ListValue.wrap(b.getGenerationSettings().getStructureFeatures().stream().map(str -> ValueConversions.of(registry.getId(str.get())))); - //}); }}; } diff --git a/src/main/java/carpet/script/utils/EquipmentInventory.java b/src/main/java/carpet/script/utils/EquipmentInventory.java index 05543625..a4021a18 100644 --- a/src/main/java/carpet/script/utils/EquipmentInventory.java +++ b/src/main/java/carpet/script/utils/EquipmentInventory.java @@ -2,6 +2,7 @@ package carpet.script.utils; import java.util.Arrays; import java.util.List; + import net.minecraft.world.Container; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; @@ -17,7 +18,8 @@ public class EquipmentInventory implements Container ); LivingEntity mob; - public EquipmentInventory(LivingEntity mob) + + public EquipmentInventory(final LivingEntity mob) { this.mob = mob; } @@ -31,20 +33,25 @@ public class EquipmentInventory implements Container @Override public boolean isEmpty() { - for (EquipmentSlot slot: slotToSlot) - if (!mob.getItemBySlot(slot).isEmpty()) return false; + for (final EquipmentSlot slot : slotToSlot) + { + if (!mob.getItemBySlot(slot).isEmpty()) + { + return false; + } + } return true; } @Override - public ItemStack getItem(int slot) + public ItemStack getItem(final int slot) { - EquipmentSlot slotSlot; + final EquipmentSlot slotSlot; try { slotSlot = slotToSlot.get(slot); } - catch (IndexOutOfBoundsException ignored) + catch (final IndexOutOfBoundsException ignored) { //going out of the index should be really exceptional return ItemStack.EMPTY; @@ -53,14 +60,14 @@ public class EquipmentInventory implements Container } @Override - public ItemStack removeItem(int slot, int amount) + public ItemStack removeItem(final int slot, final int amount) { - EquipmentSlot slotSlot; + final EquipmentSlot slotSlot; try { slotSlot = slotToSlot.get(slot); } - catch (IndexOutOfBoundsException ignored) + catch (final IndexOutOfBoundsException ignored) { //going out of the index should be really exceptional return ItemStack.EMPTY; @@ -69,32 +76,32 @@ public class EquipmentInventory implements Container } @Override - public ItemStack removeItemNoUpdate(int slot) + public ItemStack removeItemNoUpdate(final int slot) { - EquipmentSlot slotSlot; + final EquipmentSlot slotSlot; try { slotSlot = slotToSlot.get(slot); } - catch (IndexOutOfBoundsException ignored) + catch (final IndexOutOfBoundsException ignored) { //going out of the index should be really exceptional return ItemStack.EMPTY; } - ItemStack previous = mob.getItemBySlot(slotSlot); + final ItemStack previous = mob.getItemBySlot(slotSlot); mob.setItemSlot(slotSlot, ItemStack.EMPTY); return previous; } @Override - public void setItem(int slot, ItemStack stack) + public void setItem(final int slot, final ItemStack stack) { - EquipmentSlot slotSlot; + final EquipmentSlot slotSlot; try { slotSlot = slotToSlot.get(slot); } - catch (IndexOutOfBoundsException ignored) + catch (final IndexOutOfBoundsException ignored) { //going out of the index should be really exceptional return; @@ -109,7 +116,7 @@ public class EquipmentInventory implements Container } @Override - public boolean stillValid(Player player) + public boolean stillValid(final Player player) { return false; } @@ -117,7 +124,9 @@ public class EquipmentInventory implements Container @Override public void clearContent() { - for (EquipmentSlot slot: slotToSlot) + for (final EquipmentSlot slot : slotToSlot) + { mob.setItemSlot(slot, ItemStack.EMPTY); + } } } diff --git a/src/main/java/carpet/script/utils/GlocalFlag.java b/src/main/java/carpet/script/utils/GlocalFlag.java index 3a7a0c30..52aa05c3 100644 --- a/src/main/java/carpet/script/utils/GlocalFlag.java +++ b/src/main/java/carpet/script/utils/GlocalFlag.java @@ -6,7 +6,7 @@ public class GlocalFlag extends ThreadLocal { private final boolean initial; - public GlocalFlag(boolean initial) + public GlocalFlag(final boolean initial) { this.initial = initial; } @@ -19,19 +19,20 @@ public class GlocalFlag extends ThreadLocal /** * Allows to thread-safely wrap a call while disabling a global flag and setting it back up right after. + * * @param action - callback to invoke when the wrapping is all setup - * @param - returned value of that action, whatever that might be + * @param - returned value of that action, whatever that might be * @return result of the action */ - public T getWhileDisabled(Supplier action) + public T getWhileDisabled(final Supplier action) { return whileValueReturn(!initial, action); } - private T whileValueReturn(boolean what, Supplier action) + private T whileValueReturn(final boolean what, final Supplier action) { T result; - boolean previous; + final boolean previous; synchronized (this) { previous = get(); @@ -48,11 +49,14 @@ public class GlocalFlag extends ThreadLocal return result; } - public T runIfEnabled(Supplier action) + public T runIfEnabled(final Supplier action) { synchronized (this) { - if (get() != initial) return null; + if (get() != initial) + { + return null; + } set(!initial); } T result; diff --git a/src/main/java/carpet/script/utils/InputValidator.java b/src/main/java/carpet/script/utils/InputValidator.java index 520b9e5d..2f71b30f 100644 --- a/src/main/java/carpet/script/utils/InputValidator.java +++ b/src/main/java/carpet/script/utils/InputValidator.java @@ -3,27 +3,31 @@ package carpet.script.utils; import carpet.script.exception.InternalExpressionException; import java.util.Locale; + import net.minecraft.ResourceLocationException; import net.minecraft.resources.ResourceLocation; -public class InputValidator { - public static String validateSimpleString(String input, boolean strict) +public class InputValidator +{ + public static String validateSimpleString(final String input, final boolean strict) { - String simplified = input.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9+_]", ""); + final String simplified = input.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9+_]", ""); if (simplified.isEmpty() || (strict && !simplified.equals(input))) + { throw new InternalExpressionException("simple name can only contain numbers, letter and _"); + } return simplified; } - public static ResourceLocation identifierOf(String string) + public static ResourceLocation identifierOf(final String string) { try { return new ResourceLocation(string); } - catch (ResourceLocationException iie) + catch (final ResourceLocationException iie) { - throw new InternalExpressionException("Incorrect identifier format '"+string+"': "+iie.getMessage()); + throw new InternalExpressionException("Incorrect identifier format '" + string + "': " + iie.getMessage()); } } diff --git a/src/main/java/carpet/script/utils/PerlinNoiseSampler.java b/src/main/java/carpet/script/utils/PerlinNoiseSampler.java index c57973d9..4fdb3f1a 100644 --- a/src/main/java/carpet/script/utils/PerlinNoiseSampler.java +++ b/src/main/java/carpet/script/utils/PerlinNoiseSampler.java @@ -6,7 +6,8 @@ import java.util.Map; import java.util.Random; // extracted from import net.minecraft.util.math.noise.PerlinNoiseSampler -public class PerlinNoiseSampler { +public class PerlinNoiseSampler +{ protected static final int[][] gradients3d = new int[][]{ {1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0}, {1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, @@ -23,49 +24,50 @@ public class PerlinNoiseSampler { public static PerlinNoiseSampler instance = new PerlinNoiseSampler(new Random(0)); public static Map samplers = new Long2ObjectOpenHashMap<>(); - public static PerlinNoiseSampler getPerlin(long aLong) + public static PerlinNoiseSampler getPerlin(final long aLong) { if (samplers.size() > 256) + { samplers.clear(); + } return samplers.computeIfAbsent(aLong, seed -> new PerlinNoiseSampler(new Random(seed))); } - public PerlinNoiseSampler(Random random) { + public PerlinNoiseSampler(final Random random) + { this.originX = random.nextDouble() * 256.0D; this.originY = random.nextDouble() * 256.0D; this.originZ = random.nextDouble() * 256.0D; this.permutations = new byte[256]; int j; - for(j = 0; j < 256; ++j) { - this.permutations[j] = (byte)j; + for (j = 0; j < 256; ++j) + { + this.permutations[j] = (byte) j; } - - for(j = 0; j < 256; ++j) { - int k = random.nextInt(256 - j); - byte b = this.permutations[j]; + for (j = 0; j < 256; ++j) + { + final int k = random.nextInt(256 - j); + final byte b = this.permutations[j]; this.permutations[j] = this.permutations[j + k]; this.permutations[j + k] = b; } - } - - - //3D - public double sample3d(double x, double y, double z) {//, double d, double e) { - double f = x + this.originX; - double g = y + this.originY; - double h = z + this.originZ; - int i = floor(f); - int j = floor(g); - int k = floor(h); - double l = f - (double)i; - double m = g - (double)j; - double n = h - (double)k; - double o = perlinFade(l); - double p = perlinFade(m); - double q = perlinFade(n); + public double sample3d(final double x, final double y, final double z) + {//, double d, double e) { + final double f = x + this.originX; + final double g = y + this.originY; + final double h = z + this.originZ; + final int i = floor(f); + final int j = floor(g); + final int k = floor(h); + final double l = f - (double) i; + final double m = g - (double) j; + final double n = h - (double) k; + final double o = perlinFade(l); + final double p = perlinFade(m); + final double q = perlinFade(n); //double t; /* if (d != 0.0D) { @@ -75,110 +77,127 @@ public class PerlinNoiseSampler { t = 0.0D; }*/ //return this.sample(i, j, k, l, m - t, n, o, p, q); - return this.sample3d(i, j, k, l, m, n, o, p, q)/2+0.5; + return this.sample3d(i, j, k, l, m, n, o, p, q) / 2 + 0.5; } - private double sample3d(int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX, double fadeLocalY, double fadeLocalZ) { - int i = this.getGradient(sectionX) + sectionY; - int j = this.getGradient(i) + sectionZ; - int k = this.getGradient(i + 1) + sectionZ; - int l = this.getGradient(sectionX + 1) + sectionY; - int m = this.getGradient(l) + sectionZ; - int n = this.getGradient(l + 1) + sectionZ; - double d = grad3d(this.getGradient(j), localX, localY, localZ); - double e = grad3d(this.getGradient(m), localX - 1.0D, localY, localZ); - double f = grad3d(this.getGradient(k), localX, localY - 1.0D, localZ); - double g = grad3d(this.getGradient(n), localX - 1.0D, localY - 1.0D, localZ); - double h = grad3d(this.getGradient(j + 1), localX, localY, localZ - 1.0D); - double o = grad3d(this.getGradient(m + 1), localX - 1.0D, localY, localZ - 1.0D); - double p = grad3d(this.getGradient(k + 1), localX, localY - 1.0D, localZ - 1.0D); - double q = grad3d(this.getGradient(n + 1), localX - 1.0D, localY - 1.0D, localZ - 1.0D); + private double sample3d(final int sectionX, final int sectionY, final int sectionZ, final double localX, final double localY, final double localZ, final double fadeLocalX, final double fadeLocalY, final double fadeLocalZ) + { + final int i = this.getGradient(sectionX) + sectionY; + final int j = this.getGradient(i) + sectionZ; + final int k = this.getGradient(i + 1) + sectionZ; + final int l = this.getGradient(sectionX + 1) + sectionY; + final int m = this.getGradient(l) + sectionZ; + final int n = this.getGradient(l + 1) + sectionZ; + final double d = grad3d(this.getGradient(j), localX, localY, localZ); + final double e = grad3d(this.getGradient(m), localX - 1.0D, localY, localZ); + final double f = grad3d(this.getGradient(k), localX, localY - 1.0D, localZ); + final double g = grad3d(this.getGradient(n), localX - 1.0D, localY - 1.0D, localZ); + final double h = grad3d(this.getGradient(j + 1), localX, localY, localZ - 1.0D); + final double o = grad3d(this.getGradient(m + 1), localX - 1.0D, localY, localZ - 1.0D); + final double p = grad3d(this.getGradient(k + 1), localX, localY - 1.0D, localZ - 1.0D); + final double q = grad3d(this.getGradient(n + 1), localX - 1.0D, localY - 1.0D, localZ - 1.0D); return lerp3(fadeLocalX, fadeLocalY, fadeLocalZ, d, e, f, g, h, o, p, q); } - private static double grad3d(int hash, double x, double y, double z) { - int i = hash & 15; + private static double grad3d(final int hash, final double x, final double y, final double z) + { + final int i = hash & 15; return dot3d(gradients3d[i], x, y, z); } - protected static double dot3d(int[] gArr, double x, double y, double z) { - return (double)gArr[0] * x + (double)gArr[1] * y + (double)gArr[2] * z; + protected static double dot3d(final int[] gArr, final double x, final double y, final double z) + { + return gArr[0] * x + gArr[1] * y + gArr[2] * z; } - public static double lerp3(double deltaX, double deltaY, double deltaZ, double d, double e, double f, double g, double h, double i, double j, double k) { + public static double lerp3(final double deltaX, final double deltaY, final double deltaZ, final double d, final double e, final double f, final double g, final double h, final double i, final double j, final double k) + { return lerp(deltaZ, lerp2(deltaX, deltaY, d, e, f, g), lerp2(deltaX, deltaY, h, i, j, k)); } //2D - public double sample2d(double x, double y) {//, double d, double e) { - double f = x + this.originX; - double g = y + this.originY; - int i = floor(f); - int j = floor(g); - double l = f - (double)i; - double m = g - (double)j; - double o = perlinFade(l); - double p = perlinFade(m); - return this.sample2d(i, j, l, m, o, p)/2+0.5; + public double sample2d(final double x, final double y) + { + final double f = x + this.originX; + final double g = y + this.originY; + final int i = floor(f); + final int j = floor(g); + final double l = f - (double) i; + final double m = g - (double) j; + final double o = perlinFade(l); + final double p = perlinFade(m); + return this.sample2d(i, j, l, m, o, p) / 2 + 0.5; } - private double sample2d(int sectionX, int sectionY, double localX, double localY, double fadeLocalX, double fadeLocalY) { - int j = this.getGradient(sectionX) + sectionY; - int m = this.getGradient(sectionX + 1) + sectionY; - double d = grad2d(this.getGradient(j), localX, localY); - double e = grad2d(this.getGradient(m), localX - 1.0D, localY); - double f = grad2d(this.getGradient(j+1), localX, localY - 1.0D); - double g = grad2d(this.getGradient(m+1), localX - 1.0D, localY - 1.0D); + private double sample2d(final int sectionX, final int sectionY, final double localX, final double localY, final double fadeLocalX, final double fadeLocalY) + { + final int j = this.getGradient(sectionX) + sectionY; + final int m = this.getGradient(sectionX + 1) + sectionY; + final double d = grad2d(this.getGradient(j), localX, localY); + final double e = grad2d(this.getGradient(m), localX - 1.0D, localY); + final double f = grad2d(this.getGradient(j + 1), localX, localY - 1.0D); + final double g = grad2d(this.getGradient(m + 1), localX - 1.0D, localY - 1.0D); return lerp2(fadeLocalX, fadeLocalY, d, e, f, g); } - private static double grad2d(int hash, double x, double y) { - int i = hash & 3; + private static double grad2d(final int hash, final double x, final double y) + { + final int i = hash & 3; return dot2d(gradients2d[i], x, y); } - protected static double dot2d(int[] gArr, double x, double y) { - return (double)gArr[0] * x + (double)gArr[1] * y; + protected static double dot2d(final int[] gArr, final double x, final double y) + { + return gArr[0] * x + gArr[1] * y; } - public static double lerp2(double deltaX, double deltaY, double d, double e, double f, double g) { + public static double lerp2(final double deltaX, final double deltaY, final double d, final double e, final double f, final double g) + { return lerp(deltaY, lerp(deltaX, d, e), lerp(deltaX, f, g)); } // 1D - public double sample1d(double x) {//, double d, double e) { - double f = x + this.originX; - int i = floor(f); - double l = f - (double)i; - double o = perlinFade(l); - return this.sample1d(i, l, o)+0.5; + public double sample1d(final double x) + { + final double f = x + this.originX; + final int i = floor(f); + final double l = f - i; + final double o = perlinFade(l); + return this.sample1d(i, l, o) + 0.5; } - private double sample1d(int sectionX, double localX, double fadeLocalX) { - double d = grad1d(this.getGradient(sectionX), localX); - double e = grad1d(this.getGradient(sectionX+1), localX - 1.0D); + + private double sample1d(final int sectionX, final double localX, final double fadeLocalX) + { + final double d = grad1d(this.getGradient(sectionX), localX); + final double e = grad1d(this.getGradient(sectionX + 1), localX - 1.0D); return lerp(fadeLocalX, d, e); } - private static double grad1d(int hash, double x) { - return ((hash & 1) == 0)? x:-x; + private static double grad1d(final int hash, final double x) + { + return ((hash & 1) == 0) ? x : -x; } - public static double lerp(double delta, double first, double second) { + public static double lerp(final double delta, final double first, final double second) + { return first + delta * (second - first); } // shared - public int getGradient(int hash) { + public int getGradient(final int hash) + { return this.permutations[hash & 255] & 255; } - public static double perlinFade(double d) { + public static double perlinFade(final double d) + { return d * d * d * (d * (d * 6.0D - 15.0D) + 10.0D); } - public static int floor(double d) { - int i = (int)d; - return d < (double)i ? i - 1 : i; + public static int floor(final double d) + { + final int i = (int) d; + return d < i ? i - 1 : i; } } \ No newline at end of file diff --git a/src/main/java/carpet/script/utils/ScarpetJsonDeserializer.java b/src/main/java/carpet/script/utils/ScarpetJsonDeserializer.java index 9b13ddc5..c6af6003 100644 --- a/src/main/java/carpet/script/utils/ScarpetJsonDeserializer.java +++ b/src/main/java/carpet/script/utils/ScarpetJsonDeserializer.java @@ -20,15 +20,17 @@ import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; -public class ScarpetJsonDeserializer implements JsonDeserializer{ +public class ScarpetJsonDeserializer implements JsonDeserializer +{ @Override - public Value deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { + public Value deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException + { return parseElement(json); } - - private Value parseElement(JsonElement element) throws JsonParseException { + + private Value parseElement(final JsonElement element) throws JsonParseException + { if (element.isJsonObject()) { return parseMap(element.getAsJsonObject()); @@ -44,23 +46,22 @@ public class ScarpetJsonDeserializer implements JsonDeserializer{ return Value.NULL; } - private Value parseMap(JsonObject jsonMap) throws JsonParseException { - Map map = new HashMap(); - jsonMap.entrySet().forEach(entry -> { - map.put(new StringValue(entry.getKey()), parseElement(entry.getValue())); - }); + private Value parseMap(final JsonObject jsonMap) throws JsonParseException + { + final Map map = new HashMap<>(); + jsonMap.entrySet().forEach(entry -> map.put(new StringValue(entry.getKey()), parseElement(entry.getValue()))); return MapValue.wrap(map); } - private Value parseList(JsonArray jsonList) throws JsonParseException { - List list = new ArrayList(); - jsonList.forEach(elem -> { - list.add(parseElement(elem)); - }); + private Value parseList(final JsonArray jsonList) throws JsonParseException + { + final List list = new ArrayList<>(); + jsonList.forEach(elem -> list.add(parseElement(elem))); return new ListValue(list); } - - private Value parsePrimitive(JsonPrimitive primitive) throws JsonParseException { + + private Value parsePrimitive(final JsonPrimitive primitive) throws JsonParseException + { if (primitive.isString()) { return new StringValue(primitive.getAsString()); diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 787c24a6..7bf3ffa0 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -52,6 +52,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -70,36 +71,47 @@ import static java.util.Map.entry; public class ShapeDispatcher { - public static record ShapeWithConfig(ExpiringShape shape, Map config) {} + public record ShapeWithConfig(ExpiringShape shape, Map config) + { + } public static ShapeWithConfig fromFunctionArgs( - MinecraftServer server, ServerLevel world, - List lv, - Set playerSet + final MinecraftServer server, final ServerLevel world, + final List lv, + final Set playerSet ) { - if (lv.size() < 3) throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params"); - String shapeType = lv.get(0).getString(); - Value duration = NumericValue.asNumber(lv.get(1), "duration"); - Map params; + if (lv.size() < 3) + { + throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params"); + } + final String shapeType = lv.get(0).getString(); + final Value duration = NumericValue.asNumber(lv.get(1), "duration"); + final Map params; if (lv.size() == 3) { - Value paramValue = lv.get(2); - if (paramValue instanceof MapValue) + final Value paramValue = lv.get(2); + if (paramValue instanceof final MapValue map) { params = new HashMap<>(); - ((MapValue) paramValue).getMap().entrySet().forEach(e -> params.put(e.getKey().getString(),e.getValue())); + map.getMap().entrySet().forEach(e -> params.put(e.getKey().getString(), e.getValue())); } - else if (paramValue instanceof ListValue) + else if (paramValue instanceof final ListValue list) { - params = parseParams(((ListValue) paramValue).getItems()); + params = parseParams(list.getItems()); + } + else + { + throw new InternalExpressionException("Parameters for 'draw_shape' need to be defined either in a list or a map"); } - else throw new InternalExpressionException("Parameters for 'draw_shape' need to be defined either in a list or a map"); } else { - List paramList = new ArrayList<>(); - for (int i=2; i < lv.size(); i++) paramList.add(lv.get(i)); + final List paramList = new ArrayList<>(); + for (int i = 2; i < lv.size(); i++) + { + paramList.add(lv.get(i)); + } params = ShapeDispatcher.parseParams(paramList); } params.putIfAbsent("dim", new StringValue(world.dimension().location().toString())); @@ -107,17 +119,23 @@ public class ShapeDispatcher if (params.containsKey("player")) { - Value players = params.get("player"); - List playerVals; - if (players instanceof ListValue) - playerVals = ((ListValue) players).getItems(); - else - playerVals = Collections.singletonList(players); - for (Value pVal : playerVals) + final Value players = params.get("player"); + final List playerVals; + if (players instanceof final ListValue list) { - ServerPlayer player = EntityValue.getPlayerByValue(server, pVal); + playerVals = list.getItems(); + } + else + { + playerVals = Collections.singletonList(players); + } + for (final Value pVal : playerVals) + { + final ServerPlayer player = EntityValue.getPlayerByValue(server, pVal); if (player == null) - throw new InternalExpressionException("'player' parameter needs to represent an existing player, not "+pVal.getString()); + { + throw new InternalExpressionException("'player' parameter needs to represent an existing player, not " + pVal.getString()); + } playerSet.add(player); } params.remove("player"); @@ -125,121 +143,125 @@ public class ShapeDispatcher return new ShapeWithConfig(ShapeDispatcher.create(server, shapeType, params), params); } - public static void sendShape(Collection players, List shapes) + public static void sendShape(final Collection players, final List shapes) { - List clientPlayers = new ArrayList<>(); - List alternativePlayers = new ArrayList<>(); - for (ServerPlayer player : players) + final List clientPlayers = new ArrayList<>(); + final List alternativePlayers = new ArrayList<>(); + for (final ServerPlayer player : players) { - if (ServerNetworkHandler.isValidCarpetPlayer(player)) - { - clientPlayers.add(player); - } - else - { - alternativePlayers.add(player); - } + (ServerNetworkHandler.isValidCarpetPlayer(player) ? clientPlayers : alternativePlayers).add(player); } if (!clientPlayers.isEmpty()) { - ListTag tag = new ListTag(); int tagcount = 0; - for (ShapeWithConfig s : shapes) + for (final ShapeWithConfig s : shapes) { tag.add(ExpiringShape.toTag(s.config())); // 4000 shapes limit boxes - if (tagcount++>1000) + if (tagcount++ > 1000) { tagcount = 0; - Tag finalTag = tag; - clientPlayers.forEach( p -> ServerNetworkHandler.sendCustomCommand(p, "scShapes", finalTag)); + final Tag finalTag = tag; + clientPlayers.forEach(p -> ServerNetworkHandler.sendCustomCommand(p, "scShapes", finalTag)); tag = new ListTag(); } } - Tag finalTag = tag; - if (tag.size() > 0) clientPlayers.forEach( p -> ServerNetworkHandler.sendCustomCommand(p, "scShapes", finalTag)); + final Tag finalTag = tag; + if (!tag.isEmpty()) + { + clientPlayers.forEach(p -> ServerNetworkHandler.sendCustomCommand(p, "scShapes", finalTag)); + } } if (!alternativePlayers.isEmpty()) { - List> alternatives = new ArrayList<>(); + final List> alternatives = new ArrayList<>(); shapes.forEach(s -> alternatives.add(s.shape().alternative())); - alternativePlayers.forEach(p -> alternatives.forEach( a -> a.accept(p))); + alternativePlayers.forEach(p -> alternatives.forEach(a -> a.accept(p))); } } - public static ParticleOptions getParticleData(String name, RegistryAccess regs) + public static ParticleOptions getParticleData(final String name, final RegistryAccess regs) { try { return ParticleDisplay.getEffect(name, regs.lookupOrThrow(Registries.PARTICLE_TYPE)); } - catch (IllegalArgumentException e) + catch (final IllegalArgumentException e) { throw new ThrowStatement(name, Throwables.UNKNOWN_PARTICLE); } } - public static Map parseParams(List items) + public static Map parseParams(final List items) { // parses params from API function - if (items.size()%2 == 1) throw new InternalExpressionException("Shape parameters list needs to be of even size"); - Map param = new HashMap<>(); - int i = 0; - while(i < items.size()) + if (items.size() % 2 == 1) { - String name = items.get(i).getString(); - Value val = items.get(i+1); + throw new InternalExpressionException("Shape parameters list needs to be of even size"); + } + final Map param = new HashMap<>(); + int i = 0; + while (i < items.size()) + { + final String name = items.get(i).getString(); + final Value val = items.get(i + 1); param.put(name, val); i += 2; } return param; } - public static ExpiringShape create(MinecraftServer server, String shapeType, Map userParams) + public static ExpiringShape create(final MinecraftServer server, final String shapeType, final Map userParams) { userParams.put("shape", new StringValue(shapeType)); userParams.keySet().forEach(key -> { - Param param = Param.of.get(key); - if (param==null) throw new InternalExpressionException("Unknown feature for shape: "+key); + final Param param = Param.of.get(key); + if (param == null) + { + throw new InternalExpressionException("Unknown feature for shape: " + key); + } userParams.put(key, param.validate(userParams, server, userParams.get(key))); }); - BiFunction, RegistryAccess, ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeType); - if (factory == null) throw new InternalExpressionException("Unknown shape: "+shapeType); + final BiFunction, RegistryAccess, ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeType); + if (factory == null) + { + throw new InternalExpressionException("Unknown shape: " + shapeType); + } return factory.apply(userParams, server.registryAccess()); } // client - public static ExpiringShape fromTag(CompoundTag tag, Level level) + public static ExpiringShape fromTag(final CompoundTag tag, final Level level) { - Map options = new HashMap<>(); - for (String key : tag.getAllKeys()) + final Map options = new HashMap<>(); + for (final String key : tag.getAllKeys()) { - Param decoder = Param.of.get(key); - if (decoder==null) + final Param decoder = Param.of.get(key); + if (decoder == null) { - CarpetSettings.LOG.info("Unknown parameter for shape: "+key); + CarpetSettings.LOG.info("Unknown parameter for shape: " + key); return null; } - Value decodedValue = decoder.decode(tag.get(key), level); + final Value decodedValue = decoder.decode(tag.get(key), level); options.put(key, decodedValue); } - Value shapeValue = options.get("shape"); + final Value shapeValue = options.get("shape"); if (shapeValue == null) { - CarpetSettings.LOG.info("Shape id missing in "+ String.join(", ", tag.getAllKeys())); + CarpetSettings.LOG.info("Shape id missing in " + String.join(", ", tag.getAllKeys())); return null; } - BiFunction, RegistryAccess, ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeValue.getString()); + final BiFunction, RegistryAccess, ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeValue.getString()); if (factory == null) { - CarpetSettings.LOG.info("Unknown shape: "+shapeValue.getString()); + CarpetSettings.LOG.info("Unknown shape: " + shapeValue.getString()); return null; } try { return factory.apply(options, level.registryAccess()); } - catch (InternalExpressionException exc) + catch (final InternalExpressionException exc) { CarpetSettings.LOG.info(exc.getMessage()); } @@ -248,20 +270,22 @@ public class ShapeDispatcher public abstract static class ExpiringShape { - public static final Map, RegistryAccess, ExpiringShape>> shapeProviders = new HashMap<>(){{ + public static final Map, RegistryAccess, ExpiringShape>> shapeProviders = new HashMap<>() + {{ put("line", creator(Line::new)); put("box", creator(Box::new)); put("sphere", creator(Sphere::new)); put("cylinder", creator(Cylinder::new)); put("label", creator(DisplayedText::new)); - put("polygon",creator(Polyface::new)); - put("block",creator(()->new DisplayedSprite(false))); - put("item",creator(()->new DisplayedSprite(true))); + put("polygon", creator(Polyface::new)); + put("block", creator(() -> new DisplayedSprite(false))); + put("item", creator(() -> new DisplayedSprite(true))); }}; - private static BiFunction, RegistryAccess, ExpiringShape> creator(Supplier shapeFactory) + + private static BiFunction, RegistryAccess, ExpiringShape> creator(final Supplier shapeFactory) { return (o, regs) -> { - ExpiringShape shape = shapeFactory.get(); + final ExpiringShape shape = shapeFactory.get(); shape.fromOptions(o, regs); return shape; }; @@ -282,37 +306,47 @@ public class ShapeDispatcher protected boolean debug; - protected ExpiringShape() { } - - public static CompoundTag toTag(Map params) + protected ExpiringShape() { - CompoundTag tag = new CompoundTag(); + } + + public static CompoundTag toTag(final Map params) + { + final CompoundTag tag = new CompoundTag(); params.forEach((k, v) -> { - Tag valTag = Param.of.get(k).toTag(v); - if (valTag != null) tag.put(k, valTag); + final Tag valTag = Param.of.get(k).toTag(v); + if (valTag != null) + { + tag.put(k, valTag); + } }); return tag; } - private void fromOptions(Map options, RegistryAccess regs) + private void fromOptions(final Map options, final RegistryAccess regs) { - Set optional = optionalParams(); - Set required = requiredParams(); - Set all = Sets.union(optional, required); + final Set optional = optionalParams(); + final Set required = requiredParams(); + final Set all = Sets.union(optional, required); if (!all.containsAll(options.keySet())) - throw new InternalExpressionException("Received unexpected parameters for shape: "+Sets.difference(options.keySet(), all)); + { + throw new InternalExpressionException("Received unexpected parameters for shape: " + Sets.difference(options.keySet(), all)); + } if (!options.keySet().containsAll(required)) - throw new InternalExpressionException("Missing required parameters for shape: "+Sets.difference(required, options.keySet())); - options.keySet().forEach(k ->{ + { + throw new InternalExpressionException("Missing required parameters for shape: " + Sets.difference(required, options.keySet())); + } + options.keySet().forEach(k -> { if (!this.canTake(k)) - throw new InternalExpressionException("Parameter "+k+" doesn't apply for shape "+options.get("shape").getString()); + { + throw new InternalExpressionException("Parameter " + k + " doesn't apply for shape " + options.get("shape").getString()); + } }); init(options, regs); } - - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { duration = NumericValue.asNumber(options.get("duration")).getInt(); @@ -320,19 +354,20 @@ public class ShapeDispatcher lineWidth = NumericValue.asNumber(options.getOrDefault("line", optional.get("line"))).getFloat(); fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt(); - this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F; - this.fg = (float)(fillColor >> 16 & 0xFF) / 255.0F; - this.fb = (float)(fillColor >> 8 & 0xFF) / 255.0F; - this.fa = (float)(fillColor & 0xFF) / 255.0F; + this.fr = (fillColor >> 24 & 0xFF) / 255.0F; + this.fg = (fillColor >> 16 & 0xFF) / 255.0F; + this.fb = (fillColor >> 8 & 0xFF) / 255.0F; + this.fa = (fillColor & 0xFF) / 255.0F; color = NumericValue.asNumber(options.getOrDefault("color", optional.get("color"))).getInt(); - this.r = (float)(color >> 24 & 0xFF) / 255.0F; - this.g = (float)(color >> 16 & 0xFF) / 255.0F; - this.b = (float)(color >> 8 & 0xFF) / 255.0F; - this.a = (float)(color & 0xFF) / 255.0F; + this.r = (color >> 24 & 0xFF) / 255.0F; + this.g = (color >> 16 & 0xFF) / 255.0F; + this.b = (color >> 8 & 0xFF) / 255.0F; + this.a = (color & 0xFF) / 255.0F; debug = false; - if (options.containsKey("debug")) { + if (options.containsKey("debug")) + { debug = options.get("debug").getBoolean(); } @@ -351,68 +386,101 @@ public class ShapeDispatcher discreteZ = snapTo.contains("dz"); } } - public int getExpiry() { return duration; } - public Vec3 toAbsolute(Entity e, Vec3 vec, float partialTick) + + public int getExpiry() + { + return duration; + } + + public Vec3 toAbsolute(final Entity e, final Vec3 vec, final float partialTick) { return vec.add( - snapX?(discreteX ?Mth.floor(e.getX()):Mth.lerp(partialTick, e.xo, e.getX())):0.0, - snapY?(discreteY ?Mth.floor(e.getY()):Mth.lerp(partialTick, e.yo, e.getY())):0.0, - snapZ?(discreteZ ?Mth.floor(e.getZ()):Mth.lerp(partialTick, e.zo, e.getZ())):0.0 + snapX ? (discreteX ? Mth.floor(e.getX()) : Mth.lerp(partialTick, e.xo, e.getX())) : 0.0, + snapY ? (discreteY ? Mth.floor(e.getY()) : Mth.lerp(partialTick, e.yo, e.getY())) : 0.0, + snapZ ? (discreteZ ? Mth.floor(e.getZ()) : Mth.lerp(partialTick, e.zo, e.getZ())) : 0.0 ); } - public Vec3 relativiseRender(Level world, Vec3 vec, float partialTick) + + public Vec3 relativiseRender(final Level world, final Vec3 vec, final float partialTick) { - if (followEntity < 0) return vec; - Entity e = world.getEntity(followEntity); - if (e == null) return vec; + if (followEntity < 0) + { + return vec; + } + final Entity e = world.getEntity(followEntity); + if (e == null) + { + return vec; + } return toAbsolute(e, vec, partialTick); } - public Vec3 vecFromValue(Value value) + public Vec3 vecFromValue(final Value value) { - if (!(value instanceof ListValue)) throw new InternalExpressionException("decoded value of "+value.getPrettyString()+" is not a triple"); - List elements = ((ListValue) value).getItems(); + if (!(value instanceof final ListValue list)) + { + throw new InternalExpressionException("decoded value of " + value.getPrettyString() + " is not a triple"); + } + final List elements = list.getItems(); return new Vec3( - NumericValue.asNumber( elements.get(0)).getDouble(), - NumericValue.asNumber( elements.get(1)).getDouble(), - NumericValue.asNumber( elements.get(2)).getDouble() + NumericValue.asNumber(elements.get(0)).getDouble(), + NumericValue.asNumber(elements.get(1)).getDouble(), + NumericValue.asNumber(elements.get(2)).getDouble() ); } - protected ParticleOptions replacementParticle(RegistryAccess regs) + + protected ParticleOptions replacementParticle(final RegistryAccess regs) { - String particleName = fa ==0 ? - String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b): - String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", fr, fg, fb); + final String particleName = fa == 0 ? + String.format(Locale.ROOT, "dust %.1f %.1f %.1f 1.0", r, g, b) : + String.format(Locale.ROOT, "dust %.1f %.1f %.1f 1.0", fr, fg, fb); return getParticleData(particleName, regs); } public abstract Consumer alternative(); + public long key(final RegistryAccess regs) { - if (key!=0) return key; + if (key != 0) + { + return key; + } key = calcKey(regs); return key; } + protected long calcKey(final RegistryAccess regs) { // using FNV-1a algorithm long hash = -3750763034362895579L; - hash ^= shapeDimension.hashCode(); hash *= 1099511628211L; - hash ^= color; hash *= 1099511628211L; - hash ^= followEntity; hash *= 1099511628211L; - hash ^= Boolean.hashCode(debug); hash *= 1099511628211L; + hash ^= shapeDimension.hashCode(); + hash *= 1099511628211L; + hash ^= color; + hash *= 1099511628211L; + hash ^= followEntity; + hash *= 1099511628211L; + hash ^= Boolean.hashCode(debug); + hash *= 1099511628211L; if (followEntity >= 0) { - hash ^= snapTo.hashCode(); hash *= 1099511628211L; + hash ^= snapTo.hashCode(); + hash *= 1099511628211L; + } + hash ^= Float.hashCode(lineWidth); + hash *= 1099511628211L; + if (fa != 0.0) + { + hash = 31 * hash + fillColor; + hash *= 1099511628211L; } - hash ^= Float.hashCode(lineWidth); hash *= 1099511628211L; - if (fa != 0.0) { hash = 31*hash + fillColor; hash *= 1099511628211L; } return hash; } + private static final double xdif = new Random().nextDouble(); private static final double ydif = new Random().nextDouble(); private static final double zdif = new Random().nextDouble(); - int vec3dhash(Vec3 vec) + + int vec3dhash(final Vec3 vec) { return vec.add(xdif, ydif, zdif).hashCode(); } @@ -427,11 +495,19 @@ public class ShapeDispatcher "fill", new NumericValue(0xffffff00), "snap", new StringValue("xyz") ); - protected Set requiredParams() {return required;} - // list of params that can be there, with defaults - protected Set optionalParams() {return optional.keySet();} - private boolean canTake(String param) + protected Set requiredParams() + { + return required; + } + + // list of params that can be there, with defaults + protected Set optionalParams() + { + return optional.keySet(); + } + + private boolean canTake(final String param) { return requiredParams().contains(param) || optionalParams().contains(param); } @@ -452,11 +528,22 @@ public class ShapeDispatcher entry("size", new NumericValue(10)), entry("value", Value.NULL), entry("doublesided", new NumericValue(0))); + @Override - protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + protected Set requiredParams() + { + return Sets.union(super.requiredParams(), required); + } + @Override - protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } - public DisplayedText() { } + protected Set optionalParams() + { + return Sets.union(super.optionalParams(), optional.keySet()); + } + + public DisplayedText() + { + } Vec3 pos; String text; @@ -476,28 +563,32 @@ public class ShapeDispatcher boolean doublesided; @Override - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { super.init(options, regs); pos = vecFromValue(options.get("pos")); - value = ((FormattedTextValue)options.get("text")).getText(); + value = ((FormattedTextValue) options.get("text")).getText(); text = value.getString(); if (options.containsKey("value")) { - value = ((FormattedTextValue)options.get("value")).getText(); + value = ((FormattedTextValue) options.get("value")).getText(); } textcolor = rgba2argb(color); textbck = rgba2argb(fillColor); - String dir = options.getOrDefault("facing", optional.get("facing")).getString(); + final String dir = options.getOrDefault("facing", optional.get("facing")).getString(); facing = ShapeDirection.fromString(dir); align = 0; if (options.containsKey("align")) { - String alignStr = options.get("align").getString(); + final String alignStr = options.get("align").getString(); if ("right".equalsIgnoreCase(alignStr)) + { align = 1; + } else if ("left".equalsIgnoreCase(alignStr)) + { align = -1; + } } doublesided = false; if (options.containsKey("doublesided")) @@ -515,63 +606,86 @@ public class ShapeDispatcher size = NumericValue.asNumber(options.getOrDefault("size", optional.get("size"))).getFloat(); } - private int rgba2argb(int color) + private int rgba2argb(final int color) { - int r = Math.max(1, color >> 24 & 0xFF); - int g = Math.max(1, color >> 16 & 0xFF); - int b = Math.max(1, color >> 8 & 0xFF); - int a = color & 0xFF; + final int r = Math.max(1, color >> 24 & 0xFF); + final int g = Math.max(1, color >> 16 & 0xFF); + final int b = Math.max(1, color >> 8 & 0xFF); + final int a = color & 0xFF; return (a << 24) + (r << 16) + (g << 8) + b; } - @Override public Consumer alternative() { - return s -> {}; + return s -> { + }; } @Override public long calcKey(final RegistryAccess regs) { long hash = super.calcKey(regs); - hash ^= 5; hash *= 1099511628211L; - hash ^= vec3dhash(pos); hash *= 1099511628211L; - hash ^= text.hashCode(); hash *= 1099511628211L; - if (facing!= null) hash ^= facing.hashCode(); hash *= 1099511628211L; - hash ^= Float.hashCode(raise); hash *= 1099511628211L; - hash ^= Float.hashCode(tilt); hash *= 1099511628211L; - hash ^= Float.hashCode(lean); hash *= 1099511628211L; - hash ^= Float.hashCode(turn); hash *= 1099511628211L; - hash ^= Float.hashCode(indent); hash *= 1099511628211L; - hash ^= Float.hashCode(height); hash *= 1099511628211L; - hash ^= Float.hashCode(size); hash *= 1099511628211L; - hash ^= Integer.hashCode(align); hash *= 1099511628211L; - hash ^= Boolean.hashCode(doublesided); hash *= 1099511628211L; + hash ^= 5; + hash *= 1099511628211L; + hash ^= vec3dhash(pos); + hash *= 1099511628211L; + hash ^= text.hashCode(); + hash *= 1099511628211L; + if (facing != null) + { + hash ^= facing.hashCode(); + } + hash *= 1099511628211L; + hash ^= Float.hashCode(raise); + hash *= 1099511628211L; + hash ^= Float.hashCode(tilt); + hash *= 1099511628211L; + hash ^= Float.hashCode(lean); + hash *= 1099511628211L; + hash ^= Float.hashCode(turn); + hash *= 1099511628211L; + hash ^= Float.hashCode(indent); + hash *= 1099511628211L; + hash ^= Float.hashCode(height); + hash *= 1099511628211L; + hash ^= Float.hashCode(size); + hash *= 1099511628211L; + hash ^= Integer.hashCode(align); + hash *= 1099511628211L; + hash ^= Boolean.hashCode(doublesided); + hash *= 1099511628211L; return hash; } } - public static class DisplayedSprite extends ExpiringShape { + public static class DisplayedSprite extends ExpiringShape + { private final Set required = Set.of("pos"); private final Map optional = Map.ofEntries( entry("facing", new StringValue("north")), entry("tilt", new NumericValue(0)), entry("lean", new NumericValue(0)), entry("turn", new NumericValue(0)), - entry("scale", ListValue.fromTriple(1,1,1)), + entry("scale", ListValue.fromTriple(1, 1, 1)), entry("blocklight", new NumericValue(-1)), entry("skylight", new NumericValue(-1))); - private boolean isitem; + private final boolean isitem; @Override - protected Set requiredParams() { return Sets.union(Sets.union(super.requiredParams(), required), Set.of(isitem ? "item" : "block"));} + protected Set requiredParams() + { + return Sets.union(Sets.union(super.requiredParams(), required), Set.of(isitem ? "item" : "block")); + } @Override - protected Set optionalParams() { return Sets.union(Sets.union(super.optionalParams(), optional.keySet()),isitem ? Set.of("variant") : Set.of()); } + protected Set optionalParams() + { + return Sets.union(Sets.union(super.optionalParams(), optional.keySet()), isitem ? Set.of("variant") : Set.of()); + } - public DisplayedSprite(boolean i) + public DisplayedSprite(final boolean i) { isitem = i; } @@ -596,13 +710,13 @@ public class ShapeDispatcher String itemTransformType; @Override - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { super.init(options, regs); pos = vecFromValue(options.get("pos")); if (!this.isitem) { - final BlockValue block = (BlockValue)options.get("block"); + final BlockValue block = (BlockValue) options.get("block"); blockState = block.getBlockState(); blockEntity = block.getData(); } @@ -611,9 +725,15 @@ public class ShapeDispatcher this.item = ItemStack.of(((NBTSerializableValue) options.get("item")).getCompoundTag()); } blockLight = NumericValue.asNumber(options.getOrDefault("blocklight", optional.get("blocklight"))).getInt(); - if (blockLight > 15) blockLight = 15; + if (blockLight > 15) + { + blockLight = 15; + } skyLight = NumericValue.asNumber(options.getOrDefault("skylight", optional.get("skylight"))).getInt(); - if (skyLight > 15) skyLight = 15; + if (skyLight > 15) + { + skyLight = 15; + } itemTransformType = "none"; if (options.containsKey("variant")) @@ -621,26 +741,30 @@ public class ShapeDispatcher itemTransformType = options.get("variant").getString().toLowerCase(Locale.ROOT); } - String dir = options.getOrDefault("facing", optional.get("facing")).getString(); + final String dir = options.getOrDefault("facing", optional.get("facing")).getString(); facing = ShapeDirection.fromString(dir); tilt = NumericValue.asNumber(options.getOrDefault("tilt", optional.get("tilt"))).getFloat(); lean = NumericValue.asNumber(options.getOrDefault("lean", optional.get("lean"))).getFloat(); turn = NumericValue.asNumber(options.getOrDefault("turn", optional.get("turn"))).getFloat(); - List scale = ((ListValue) options.getOrDefault("scale", optional.get("scale"))).unpack(); + final List scale = ((ListValue) options.getOrDefault("scale", optional.get("scale"))).unpack(); scaleY = NumericValue.asNumber(scale.get(1)).getFloat(); scaleX = NumericValue.asNumber(scale.get(0)).getFloat(); scaleZ = NumericValue.asNumber(scale.get(2)).getFloat(); } @Override - public Consumer alternative() { + public Consumer alternative() + { return p -> { - ParticleOptions particle; + final ParticleOptions particle; final Registry blocks = p.getServer().registryAccess().registryOrThrow(Registries.BLOCK); - if(this.isitem) + if (this.isitem) { - if (Block.byItem(this.item.getItem()).defaultBlockState().isAir()) return; + if (Block.byItem(this.item.getItem()).defaultBlockState().isAir()) + { + return; + } particle = getParticleData("block_marker " + blocks.getKey(Block.byItem(this.item.getItem())), p.level.registryAccess()); } else @@ -648,30 +772,56 @@ public class ShapeDispatcher particle = getParticleData("block_marker " + blocks.getKey(this.blockState.getBlock()), p.level.registryAccess()); } - Vec3 v = relativiseRender(p.level, this.pos, 0); - p.getLevel().sendParticles(p, particle , true, v.x, v.y, v.z, 1,0.0, 0.0, 0.0, 0.0); + final Vec3 v = relativiseRender(p.level, this.pos, 0); + p.getLevel().sendParticles(p, particle, true, v.x, v.y, v.z, 1, 0.0, 0.0, 0.0, 0.0); }; } @Override - public long calcKey(final RegistryAccess regs) { + public long calcKey(final RegistryAccess regs) + { long hash = super.calcKey(regs); - hash ^= 7; hash *= 1099511628211L; - hash ^= Boolean.hashCode(isitem); hash *= 1099511628211L; - hash ^= vec3dhash(pos); hash *= 1099511628211L; - if (facing!= null) hash ^= facing.hashCode(); hash *= 1099511628211L; - hash ^= Float.hashCode(tilt); hash *= 1099511628211L; - hash ^= Float.hashCode(lean); hash *= 1099511628211L; - hash ^= Float.hashCode(turn); hash *= 1099511628211L; - hash ^= Float.hashCode(scaleY); hash *= 1099511628211L; - hash ^= Float.hashCode(scaleZ); hash *= 1099511628211L; - hash ^= Float.hashCode(scaleX); hash *= 1099511628211L; - hash ^= Float.hashCode(skyLight); hash *= 1099511628211L; - hash ^= Float.hashCode(blockLight); hash *= 1099511628211L; - if (blockEntity!= null) hash ^= blockEntity.toString().hashCode(); hash *= 1099511628211L; - if (blockState!= null) hash ^= blockState.hashCode(); hash *= 1099511628211L; - hash ^= ValueConversions.of(item, regs).getString().hashCode(); hash *= 1099511628211L; - hash ^= itemTransformType.hashCode(); hash *= 1099511628211L; + hash ^= 7; + hash *= 1099511628211L; + hash ^= Boolean.hashCode(isitem); + hash *= 1099511628211L; + hash ^= vec3dhash(pos); + hash *= 1099511628211L; + if (facing != null) + { + hash ^= facing.hashCode(); + } + hash *= 1099511628211L; + hash ^= Float.hashCode(tilt); + hash *= 1099511628211L; + hash ^= Float.hashCode(lean); + hash *= 1099511628211L; + hash ^= Float.hashCode(turn); + hash *= 1099511628211L; + hash ^= Float.hashCode(scaleY); + hash *= 1099511628211L; + hash ^= Float.hashCode(scaleZ); + hash *= 1099511628211L; + hash ^= Float.hashCode(scaleX); + hash *= 1099511628211L; + hash ^= Float.hashCode(skyLight); + hash *= 1099511628211L; + hash ^= Float.hashCode(blockLight); + hash *= 1099511628211L; + if (blockEntity != null) + { + hash ^= blockEntity.toString().hashCode(); + } + hash *= 1099511628211L; + if (blockState != null) + { + hash ^= blockState.hashCode(); + } + hash *= 1099511628211L; + hash ^= ValueConversions.of(item, regs).getString().hashCode(); + hash *= 1099511628211L; + hash ^= itemTransformType.hashCode(); + hash *= 1099511628211L; return hash; } @@ -682,17 +832,28 @@ public class ShapeDispatcher { private final Set required = Set.of("from", "to"); private final Map optional = Map.of(); + @Override - protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + protected Set requiredParams() + { + return Sets.union(super.requiredParams(), required); + } + @Override - protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } - public Box() { } + protected Set optionalParams() + { + return Sets.union(super.optionalParams(), optional.keySet()); + } + + public Box() + { + } Vec3 from; Vec3 to; @Override - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { super.init(options, regs); from = vecFromValue(options.get("from")); @@ -702,7 +863,7 @@ public class ShapeDispatcher @Override public Consumer alternative() { - double density = Math.max(2.0, from.distanceTo(to) /50/ (a+0.1)) ; + final double density = Math.max(2.0, from.distanceTo(to) / 50 / (a + 0.1)); return p -> { if (p.level.dimension() == shapeDimension) @@ -722,215 +883,285 @@ public class ShapeDispatcher public long calcKey(final RegistryAccess regs) { long hash = super.calcKey(regs); - hash ^= 1; hash *= 1099511628211L; - hash ^= vec3dhash(from); hash *= 1099511628211L; - hash ^= vec3dhash(to); hash *= 1099511628211L; + hash ^= 1; + hash *= 1099511628211L; + hash ^= vec3dhash(from); + hash *= 1099511628211L; + hash ^= vec3dhash(to); + hash *= 1099511628211L; return hash; } - public static int particleMesh(List playerList, ParticleOptions particle, double density, - Vec3 from, Vec3 to) + public static int particleMesh(final List playerList, final ParticleOptions particle, final double density, + final Vec3 from, final Vec3 to) { - double x1 = from.x; - double y1 = from.y; - double z1 = from.z; - double x2 = to.x; - double y2 = to.y; - double z2 = to.z; + final double x1 = from.x; + final double y1 = from.y; + final double z1 = from.z; + final double x2 = to.x; + final double y2 = to.y; + final double z2 = to.z; return - drawParticleLine(playerList, particle, new Vec3(x1, y1, z1), new Vec3(x1, y2, z1), density)+ - drawParticleLine(playerList, particle, new Vec3(x1, y2, z1), new Vec3(x2, y2, z1), density)+ - drawParticleLine(playerList, particle, new Vec3(x2, y2, z1), new Vec3(x2, y1, z1), density)+ - drawParticleLine(playerList, particle, new Vec3(x2, y1, z1), new Vec3(x1, y1, z1), density)+ + drawParticleLine(playerList, particle, new Vec3(x1, y1, z1), new Vec3(x1, y2, z1), density) + + drawParticleLine(playerList, particle, new Vec3(x1, y2, z1), new Vec3(x2, y2, z1), density) + + drawParticleLine(playerList, particle, new Vec3(x2, y2, z1), new Vec3(x2, y1, z1), density) + + drawParticleLine(playerList, particle, new Vec3(x2, y1, z1), new Vec3(x1, y1, z1), density) + - drawParticleLine(playerList, particle, new Vec3(x1, y1, z2), new Vec3(x1, y2, z2), density)+ - drawParticleLine(playerList, particle, new Vec3(x1, y2, z2), new Vec3(x2, y2, z2), density)+ - drawParticleLine(playerList, particle, new Vec3(x2, y2, z2), new Vec3(x2, y1, z2), density)+ - drawParticleLine(playerList, particle, new Vec3(x2, y1, z2), new Vec3(x1, y1, z2), density)+ + drawParticleLine(playerList, particle, new Vec3(x1, y1, z2), new Vec3(x1, y2, z2), density) + + drawParticleLine(playerList, particle, new Vec3(x1, y2, z2), new Vec3(x2, y2, z2), density) + + drawParticleLine(playerList, particle, new Vec3(x2, y2, z2), new Vec3(x2, y1, z2), density) + + drawParticleLine(playerList, particle, new Vec3(x2, y1, z2), new Vec3(x1, y1, z2), density) + - drawParticleLine(playerList, particle, new Vec3(x1, y1, z1), new Vec3(x1, y1, z2), density)+ - drawParticleLine(playerList, particle, new Vec3(x1, y2, z1), new Vec3(x1, y2, z2), density)+ - drawParticleLine(playerList, particle, new Vec3(x2, y2, z1), new Vec3(x2, y2, z2), density)+ - drawParticleLine(playerList, particle, new Vec3(x2, y1, z1), new Vec3(x2, y1, z2), density); + drawParticleLine(playerList, particle, new Vec3(x1, y1, z1), new Vec3(x1, y1, z2), density) + + drawParticleLine(playerList, particle, new Vec3(x1, y2, z1), new Vec3(x1, y2, z2), density) + + drawParticleLine(playerList, particle, new Vec3(x2, y2, z1), new Vec3(x2, y2, z2), density) + + drawParticleLine(playerList, particle, new Vec3(x2, y1, z1), new Vec3(x2, y1, z2), density); } } public static class Polyface extends ExpiringShape { @Override - public long calcKey(final RegistryAccess regs){ + public long calcKey(final RegistryAccess regs) + { long hash = super.calcKey(regs); - hash ^= 6; hash *= 1099511628211L; - hash ^= mode; hash *= 1099511628211L; - hash ^= relative.hashCode(); hash *= 1099511628211L; - for (Vec3 i :vertex_list){ + hash ^= 6; + hash *= 1099511628211L; + hash ^= mode; + hash *= 1099511628211L; + hash ^= relative.hashCode(); + hash *= 1099511628211L; + for (final Vec3 i : vertex_list) + { hash ^= vec3dhash(i); hash *= 1099511628211L; } - hash ^= Boolean.hashCode(doublesided); hash *= 1099511628211L; - hash ^= Integer.hashCode(vertex_list.size()); hash *= 1099511628211L; - hash ^= Boolean.hashCode(inneredges); hash *= 1099511628211L; + hash ^= Boolean.hashCode(doublesided); + hash *= 1099511628211L; + hash ^= Integer.hashCode(vertex_list.size()); + hash *= 1099511628211L; + hash ^= Boolean.hashCode(inneredges); + hash *= 1099511628211L; return hash; } - ArrayList alter_point=null; - final Random random=new Random(); + + ArrayList alter_point = null; + final Random random = new Random(); boolean doublesided; - ArrayList alter_point(ServerPlayer p){ - if (alter_point!=null){ + ArrayList alter_point(final ServerPlayer p) + { + if (alter_point != null) + { return alter_point; } - alter_point=new ArrayList<>(); - switch (mode) { + alter_point = new ArrayList<>(); + switch (mode) + { case 4: - for (int i=0;i alternative() { - return p->{ - if(p.level.dimension() != this.shapeDimension){return;} - if(!(fa>0.0f)){return;} - final ParticleOptions locparticledata = getParticleData(String.format(Locale.ROOT ,"dust %.1f %.1f %.1f %.1f", fr, fg, fb, fa), p.level.registryAccess()); - for(Vec3 v : alter_point(p)){ - p.getLevel().sendParticles(p,locparticledata , true, - v.x, v.y, v.z, 1, - 0.0, 0.0, 0.0, 0.0); + public Consumer alternative() + { + return p -> { + if (p.level.dimension() != this.shapeDimension) + { + return; + } + if (!(fa > 0.0f)) + { + return; + } + final ParticleOptions locparticledata = getParticleData(String.format(Locale.ROOT, "dust %.1f %.1f %.1f %.1f", fr, fg, fb, fa), p.level.registryAccess()); + for (final Vec3 v : alter_point(p)) + { + p.getLevel().sendParticles(p, locparticledata, true, + v.x, v.y, v.z, 1, + 0.0, 0.0, 0.0, 0.0); } }; } + private final Set required = Set.of("points"); private final Map optional = Map.ofEntries( - entry("relative",Value.NULL), - entry("mode", new StringValue("polygon")), - entry("inner", Value.TRUE), - entry("doublesided", Value.TRUE) + entry("relative", Value.NULL), + entry("mode", new StringValue("polygon")), + entry("inner", Value.TRUE), + entry("doublesided", Value.TRUE) ); + @Override - protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + protected Set requiredParams() + { + return Sets.union(super.requiredParams(), required); + } + @Override - protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } - ArrayList vertex_list=new ArrayList<>(); + protected Set optionalParams() + { + return Sets.union(super.optionalParams(), optional.keySet()); + } + + ArrayList vertex_list = new ArrayList<>(); int mode; - ArrayList relative=new ArrayList<>(); + ArrayList relative = new ArrayList<>(); boolean inneredges; + @Override - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { super.init(options, regs); - doublesided=options.getOrDefault("doublesided",optional.get("doublesided")).getBoolean(); - - if (options.get("points") instanceof AbstractListValue abl){ - abl.forEach(x->vertex_list.add(vecFromValue(x))); + doublesided = options.getOrDefault("doublesided", optional.get("doublesided")).getBoolean(); + + if (options.get("points") instanceof final AbstractListValue abl) + { + abl.forEach(x -> vertex_list.add(vecFromValue(x))); } - String _mode = options.getOrDefault("mode",optional.get("mode")).getString(); - inneredges = options.getOrDefault("inner",optional.get("inner")).getBoolean(); - if(vertex_list.size()<3){ + final String _mode = options.getOrDefault("mode", optional.get("mode")).getString(); + inneredges = options.getOrDefault("inner", optional.get("inner")).getBoolean(); + if (vertex_list.size() < 3) + { throw new IllegalArgumentException("Unexpected vertex list size: " + vertex_list.size()); - }else if(vertex_list.size()<4){ - inneredges=false; } - if("polygon".equals(_mode)){ - mode=6; - }else if("strip".equals(_mode)){ - mode=5; - }else if("triangles".equals(_mode)){ - mode=4; - if(vertex_list.size()%3!=0){ + else if (vertex_list.size() < 4) + { + inneredges = false; + } + if ("polygon".equals(_mode)) + { + mode = 6; + } + else if ("strip".equals(_mode)) + { + mode = 5; + } + else if ("triangles".equals(_mode)) + { + mode = 4; + if (vertex_list.size() % 3 != 0) + { throw new IllegalArgumentException("Unexpected vertex list size: " + vertex_list.size()); } } - if (options.getOrDefault("relative",optional.get("relative")) instanceof AbstractListValue abl){ - Iterator it = abl.iterator(); - for(long i=0L;i it = abl.iterator(); + for (long i = 0L; i < vertex_list.size(); i++) + { + relative.add(it.hasNext() && it.next().getBoolean());//if part of it got defined. } } - else if(options.getOrDefault("relative",optional.get("relative")) instanceof BooleanValue boolv){ - for(long i=0L;i required = Set.of("from", "to"); private final Map optional = Map.of(); + @Override - protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + protected Set requiredParams() + { + return Sets.union(super.requiredParams(), required); + } + @Override - protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + protected Set optionalParams() + { + return Sets.union(super.optionalParams(), optional.keySet()); + } private Line() { @@ -952,7 +1191,7 @@ public class ShapeDispatcher Vec3 to; @Override - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { super.init(options, regs); from = vecFromValue(options.get("from")); @@ -962,16 +1201,19 @@ public class ShapeDispatcher @Override public Consumer alternative() { - double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); + final double density = Math.max(2.0, from.distanceTo(to) / 50) / (a + 0.1); return p -> { - if (p.level.dimension() == shapeDimension) drawParticleLine( - Collections.singletonList(p), - replacementParticle(p.level.registryAccess()), - relativiseRender(p.level, from, 0), - relativiseRender(p.level, to, 0), - density - ); + if (p.level.dimension() == shapeDimension) + { + drawParticleLine( + Collections.singletonList(p), + replacementParticle(p.level.registryAccess()), + relativiseRender(p.level, from, 0), + relativiseRender(p.level, to, 0), + density + ); + } }; } @@ -979,9 +1221,12 @@ public class ShapeDispatcher public long calcKey(final RegistryAccess regs) { long hash = super.calcKey(regs); - hash ^= 2; hash *= 1099511628211L; - hash ^= vec3dhash(from); hash *= 1099511628211L; - hash ^= vec3dhash(to); hash *= 1099511628211L; + hash ^= 2; + hash *= 1099511628211L; + hash ^= vec3dhash(from); + hash *= 1099511628211L; + hash ^= vec3dhash(to); + hash *= 1099511628211L; return hash; } } @@ -990,10 +1235,18 @@ public class ShapeDispatcher { private final Set required = Set.of("center", "radius"); private final Map optional = Map.of("level", Value.ZERO); + @Override - protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + protected Set requiredParams() + { + return Sets.union(super.requiredParams(), required); + } + @Override - protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + protected Set optionalParams() + { + return Sets.union(super.optionalParams(), optional.keySet()); + } private Sphere() { @@ -1006,7 +1259,7 @@ public class ShapeDispatcher int subdivisions; @Override - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { super.init(options, regs); center = vecFromValue(options.get("center")); @@ -1015,50 +1268,57 @@ public class ShapeDispatcher subdivisions = level; if (subdivisions <= 0) { - subdivisions = Math.max(10, (int)(10*Math.sqrt(radius))); + subdivisions = Math.max(10, (int) (10 * Math.sqrt(radius))); } } @Override - public Consumer alternative() { return p -> + public Consumer alternative() { - - int partno = Math.min(1000,20*subdivisions); - RandomSource rand = p.level.getRandom(); - ServerLevel world = p.getLevel(); - ParticleOptions particle = replacementParticle(world.registryAccess()); - - Vec3 ccenter = relativiseRender(world, center, 0 ); - - double ccx = ccenter.x; - double ccy = ccenter.y; - double ccz = ccenter.z; - - for (int i=0; i { - float theta = (float)Math.asin(rand.nextDouble()*2.0-1.0); - float phi = (float)(2*Math.PI*rand.nextDouble()); + final int partno = Math.min(1000, 20 * subdivisions); + final RandomSource rand = p.level.getRandom(); + final ServerLevel world = p.getLevel(); + final ParticleOptions particle = replacementParticle(world.registryAccess()); - double x = radius * Mth.cos(theta) * Mth.cos(phi); - double y = radius * Mth.cos(theta) * Mth.sin(phi); - double z = radius * Mth.sin(theta); - world.sendParticles(p, particle, true, - x+ccx, y+ccy, z+ccz, 1, - 0.0, 0.0, 0.0, 0.0); - } - };} + final Vec3 ccenter = relativiseRender(world, center, 0); + + final double ccx = ccenter.x; + final double ccy = ccenter.y; + final double ccz = ccenter.z; + + for (int i = 0; i < partno; i++) + { + final float theta = (float) Math.asin(rand.nextDouble() * 2.0 - 1.0); + final float phi = (float) (2 * Math.PI * rand.nextDouble()); + + final double x = radius * Mth.cos(theta) * Mth.cos(phi); + final double y = radius * Mth.cos(theta) * Mth.sin(phi); + final double z = radius * Mth.sin(theta); + world.sendParticles(p, particle, true, + x + ccx, y + ccy, z + ccz, 1, + 0.0, 0.0, 0.0, 0.0); + } + }; + } @Override public long calcKey(final RegistryAccess regs) { long hash = super.calcKey(regs); - hash ^= 3; hash *= 1099511628211L; - hash ^= vec3dhash(center); hash *= 1099511628211L; - hash ^= Double.hashCode(radius); hash *= 1099511628211L; - hash ^= level; hash *= 1099511628211L; + hash ^= 3; + hash *= 1099511628211L; + hash ^= vec3dhash(center); + hash *= 1099511628211L; + hash ^= Double.hashCode(radius); + hash *= 1099511628211L; + hash ^= level; + hash *= 1099511628211L; return hash; } } + public static class Cylinder extends ExpiringShape { private final Set required = Set.of("center", "radius"); @@ -1067,10 +1327,18 @@ public class ShapeDispatcher "height", Value.ZERO, "axis", new StringValue("y") ); + @Override - protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + protected Set requiredParams() + { + return Sets.union(super.requiredParams(), required); + } + @Override - protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + protected Set optionalParams() + { + return Sets.union(super.optionalParams(), optional.keySet()); + } Vec3 center; float height; @@ -1079,10 +1347,13 @@ public class ShapeDispatcher int subdivisions; Direction.Axis axis; - private Cylinder() { super(); } + private Cylinder() + { + super(); + } @Override - protected void init(Map options, RegistryAccess regs) + protected void init(final Map options, final RegistryAccess regs) { super.init(options, regs); center = vecFromValue(options.get("center")); @@ -1091,7 +1362,7 @@ public class ShapeDispatcher subdivisions = level; if (subdivisions <= 0) { - subdivisions = Math.max(10, (int)(10*Math.sqrt(radius))); + subdivisions = Math.max(10, (int) (10 * Math.sqrt(radius))); } height = NumericValue.asNumber(options.getOrDefault("height", optional.get("height"))).getFloat(); axis = Direction.Axis.byName(options.getOrDefault("axis", optional.get("axis")).getString()); @@ -1099,84 +1370,92 @@ public class ShapeDispatcher @Override - public Consumer alternative() { return p -> + public Consumer alternative() { - - int partno = (int)Math.min(1000,Math.sqrt(20*subdivisions*(1+height))); - RandomSource rand = p.level.getRandom(); - ServerLevel world = p.getLevel(); - ParticleOptions particle = replacementParticle(world.registryAccess()); - - Vec3 ccenter = relativiseRender(world, center, 0 ); - - double ccx = ccenter.x; - double ccy = ccenter.y; - double ccz = ccenter.z; - - if (axis == Direction.Axis.Y) + return p -> { - for (int i=0; i of = new HashMap(){{ - put("mode",new StringChoiceParam("mode","polygon","strip","triangles")); - put("relative",new OptionalBoolListParam("relative")); + public static Map of = new HashMap() + {{ + put("mode", new StringChoiceParam("mode", "polygon", "strip", "triangles")); + put("relative", new OptionalBoolListParam("relative")); put("inner", new BoolParam("inner")); put("shape", new ShapeParam()); put("dim", new DimensionParam()); put("duration", new NonNegativeIntParam("duration")); put("color", new ColorParam("color")); put("follow", new EntityParam("follow")); - put("variant",new StringChoiceParam("variant", + put("variant", new StringChoiceParam("variant", "NONE", "THIRD_PERSON_LEFT_HAND", "THIRD_PERSON_RIGHT_HAND", @@ -1186,18 +1465,19 @@ public class ShapeDispatcher "GUI", "GROUND", "FIXED") - { - public Value validate(Map o, MinecraftServer s, Value v) - { - return super.validate(o, s ,new StringValue(v.getString().toUpperCase(Locale.ROOT))); - } - }); + { + @Override + public Value validate(final Map o, final MinecraftServer s, final Value v) + { + return super.validate(o, s, new StringValue(v.getString().toUpperCase(Locale.ROOT))); + } + }); put("snap", new StringChoiceParam("snap", "xyz", "xz", "yz", "xy", "x", "y", "z", "dxdydz", "dxdz", "dydz", "dxdy", "dx", "dy", "dz", "xdz", "dxz", "ydz", "dyz", "xdy", "dxy", "xydz", "xdyz", "xdydz", "dxyz", "dxydz", "dxdyz" - )); + )); put("line", new PositiveFloatParam("line")); put("fill", new ColorParam("fill")); @@ -1209,13 +1489,18 @@ public class ShapeDispatcher put("level", new PositiveIntParam("level")); put("height", new FloatParam("height")); put("width", new FloatParam("width")); - put("scale", new Vec3Param("scale", false){ - public Value validate(java.util.Map options, MinecraftServer server, Value value) { - if (value instanceof NumericValue vn){ - value = ListValue.of(vn,vn,vn); + put("scale", new Vec3Param("scale", false) + { + @Override + public Value validate(final java.util.Map options, final MinecraftServer server, Value value) + { + if (value instanceof final NumericValue vn) + { + value = ListValue.of(vn, vn, vn); } return super.validate(options, server, value); - }; + } + }); put("axis", new StringChoiceParam("axis", "x", "y", "z")); put("points", new PointsParam("points")); @@ -1239,71 +1524,106 @@ public class ShapeDispatcher }}; protected String id; - protected Param(String id) + + protected Param(final String id) { this.id = id; } public abstract Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize + public abstract Value validate(Map options, MinecraftServer server, Value value); // makes sure the value is proper + public abstract Value decode(Tag tag, Level level); } + public static class OptionalBoolListParam extends Param { - public OptionalBoolListParam(String id) { super(id); } + public OptionalBoolListParam(final String id) + { + super(id); + } @Override - public Tag toTag(Value value) { return value.toTag(true);} + public Tag toTag(final Value value) + { + return value.toTag(true); + } + @Override - public Value decode(Tag tag, Level level) { - if(tag instanceof ListTag){ - return ListValue.wrap(((ListTag)tag).stream().map(x->BooleanValue.of(((NumericTag)x).getAsNumber().doubleValue()!=0))); + public Value decode(final Tag tag, final Level level) + { + if (tag instanceof final ListTag list) + { + return ListValue.wrap(list.stream().map(x -> BooleanValue.of(((NumericTag) x).getAsNumber().doubleValue() != 0))); } - if(tag instanceof ByteTag booltag){ - return BooleanValue.of(booltag.getAsByte()!=0); + if (tag instanceof final ByteTag booltag) + { + return BooleanValue.of(booltag.getAsByte() != 0); } return Value.NULL; } @Override - public Value validate(Map options, MinecraftServer server, Value value) { - if(value instanceof AbstractListValue lv){ + public Value validate(final Map options, final MinecraftServer server, final Value value) + { + if (value instanceof final AbstractListValue lv) + { return ListValue.wrap(lv.unpack().stream().map(Value::getBoolean).map(BooleanValue::of)); } - if(value instanceof BooleanValue || value.isNull()){ + if (value instanceof BooleanValue || value.isNull()) + { return value; } return BooleanValue.of(value.getBoolean()); } } + public abstract static class StringParam extends Param { - protected StringParam(String id) { super(id); } - - @Override - public Tag toTag(Value value) { return StringTag.valueOf(value.getString()); } - @Override - public Value decode(Tag tag, Level level) { return new StringValue(tag.getAsString()); } - } - public static class BlockParam extends Param - { - - protected BlockParam(String id) { + protected StringParam(final String id) + { super(id); } + @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Tag toTag(final Value value) { - if(value instanceof BlockValue blv){ + return StringTag.valueOf(value.getString()); + } + + @Override + public Value decode(final Tag tag, final Level level) + { + return new StringValue(tag.getAsString()); + } + } + + public static class BlockParam extends Param + { + + protected BlockParam(final String id) + { + super(id); + } + + @Override + public Value validate(final Map options, final MinecraftServer server, final Value value) + { + if (value instanceof BlockValue) + { return value; } return BlockValue.fromString(value.getString(), server.overworld()); } + @Override - public Tag toTag(Value value) { - if(value instanceof BlockValue blv){ - CompoundTag com = NbtUtils.writeBlockState(blv.getBlockState()); - CompoundTag dataTag = blv.getData(); + public Tag toTag(final Value value) + { + if (value instanceof final BlockValue blv) + { + final CompoundTag com = NbtUtils.writeBlockState(blv.getBlockState()); + final CompoundTag dataTag = blv.getData(); if (dataTag != null) { com.put("TileEntityData", dataTag); @@ -1314,60 +1634,75 @@ public class ShapeDispatcher } @Override - public Value decode(Tag tag, Level level) { - BlockState bs = NbtUtils.readBlockState(level.holderLookup(Registries.BLOCK), (CompoundTag) tag); + public Value decode(final Tag tag, final Level level) + { + final BlockState bs = NbtUtils.readBlockState(level.holderLookup(Registries.BLOCK), (CompoundTag) tag); CompoundTag compoundTag2 = null; - if (((CompoundTag) tag).contains("TileEntityData", 10)) { - compoundTag2 = ((CompoundTag) tag).getCompound("TileEntityData"); + if (((CompoundTag) tag).contains("TileEntityData", 10)) + { + compoundTag2 = ((CompoundTag) tag).getCompound("TileEntityData"); } return new BlockValue(bs, level, null, compoundTag2); } } + public static class ItemParam extends Param { - - protected ItemParam(String id) { + + protected ItemParam(final String id) + { super(id); } + @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) { - ItemStack item=ValueConversions.getItemStackFromValue(value, true, server.registryAccess()); + final ItemStack item = ValueConversions.getItemStackFromValue(value, true, server.registryAccess()); return new NBTSerializableValue(item.save(new CompoundTag())); } + @Override - public Tag toTag(Value value) { - return ((NBTSerializableValue)value).getTag(); + public Tag toTag(final Value value) + { + return ((NBTSerializableValue) value).getTag(); } + @Override - public Value decode(Tag tag, Level level) { + public Value decode(final Tag tag, final Level level) + { return new NBTSerializableValue(tag); } } + public static class TextParam extends StringParam { - protected TextParam(String id) + protected TextParam(final String id) { super(id); } + @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) { return value; } } + public static class FormattedTextParam extends StringParam { - protected FormattedTextParam(String id) + protected FormattedTextParam(final String id) { super(id); } + @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, Value value) { if (!(value instanceof FormattedTextValue)) + { value = new FormattedTextValue(Component.literal(value.getString())); + } return value; } @@ -1375,12 +1710,14 @@ public class ShapeDispatcher public Tag toTag(Value value) { if (!(value instanceof FormattedTextValue)) + { value = new FormattedTextValue(Component.literal(value.getString())); - return StringTag.valueOf(((FormattedTextValue)value).serialize()); + } + return StringTag.valueOf(((FormattedTextValue) value).serialize()); } @Override - public Value decode(Tag tag, Level level) + public Value decode(final Tag tag, final Level level) { return FormattedTextValue.deserialize(tag.getAsString()); } @@ -1389,8 +1726,9 @@ public class ShapeDispatcher public static class StringChoiceParam extends StringParam { - private Set options; - public StringChoiceParam(String id, String ... options) + private final Set options; + + public StringChoiceParam(final String id, final String... options) { super(id); this.options = Sets.newHashSet(options); @@ -1398,201 +1736,312 @@ public class ShapeDispatcher @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) { - if (this.options.contains(value.getString())) return value; + if (this.options.contains(value.getString())) + { + return value; + } return null; } } public static class DimensionParam extends StringParam { - protected DimensionParam() { super("dim"); } + protected DimensionParam() + { + super("dim"); + } @Override - public Value validate(Map options, MinecraftServer server, Value value) { return value; } + public Value validate(final Map options, final MinecraftServer server, final Value value) + { + return value; + } } + public static class ShapeParam extends StringParam { - protected ShapeParam() { super("shape"); } + protected ShapeParam() + { + super("shape"); + } @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) { - String shape = value.getString(); + final String shape = value.getString(); if (!ExpiringShape.shapeProviders.containsKey(shape)) - throw new InternalExpressionException("Unknown shape: "+shape); + { + throw new InternalExpressionException("Unknown shape: " + shape); + } return value; } } - public static abstract class NumericParam extends Param - { - protected NumericParam(String id) { super(id); } - @Override - public Value validate(Map options, MinecraftServer server, Value value) - { - if (!(value instanceof NumericValue)) - throw new InternalExpressionException("'" + id + "' needs to be a number"); - return value; - } - } - public static class BoolParam extends NumericParam + public abstract static class NumericParam extends Param { - protected BoolParam(String id) + protected NumericParam(final String id) { super(id); } @Override - public Tag toTag(Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) + { + if (!(value instanceof NumericValue)) + { + throw new InternalExpressionException("'" + id + "' needs to be a number"); + } + return value; + } + } + + public static class BoolParam extends NumericParam + { + protected BoolParam(final String id) + { + super(id); + } + + @Override + public Tag toTag(final Value value) { return ByteTag.valueOf(value.getBoolean()); } @Override - public Value decode(Tag tag, Level level) + public Value decode(final Tag tag, final Level level) { return BooleanValue.of(((ByteTag) tag).getAsByte() > 0); } } + public static class FloatParam extends NumericParam { - protected FloatParam(String id) { super(id); } + protected FloatParam(final String id) + { + super(id); + } + @Override - public Value decode(Tag tag, Level level) { return new NumericValue(((FloatTag)tag).getAsFloat()); } + public Value decode(final Tag tag, final Level level) + { + return new NumericValue(((FloatTag) tag).getAsFloat()); + } + @Override - public Tag toTag(Value value) { return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat()); } + public Tag toTag(final Value value) + { + return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat()); + } } - public static abstract class PositiveParam extends NumericParam + public abstract static class PositiveParam extends NumericParam { - protected PositiveParam(String id) { super(id); } - @Override public Value validate(Map options, MinecraftServer server, Value value) + protected PositiveParam(final String id) { - Value ret = super.validate(options, server, value); - if (((NumericValue)ret).getDouble()<=0) throw new InternalExpressionException("'"+id+"' should be positive"); + super(id); + } + + @Override + public Value validate(final Map options, final MinecraftServer server, final Value value) + { + final Value ret = super.validate(options, server, value); + if (((NumericValue) ret).getDouble() <= 0) + { + throw new InternalExpressionException("'" + id + "' should be positive"); + } return ret; } } + public static class PositiveFloatParam extends PositiveParam { - protected PositiveFloatParam(String id) { super(id); } + protected PositiveFloatParam(final String id) + { + super(id); + } + @Override - public Value decode(Tag tag, Level level) { return new NumericValue(((FloatTag)tag).getAsFloat()); } + public Value decode(final Tag tag, final Level level) + { + return new NumericValue(((FloatTag) tag).getAsFloat()); + } + @Override - public Tag toTag(Value value) { return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat()); } + public Tag toTag(final Value value) + { + return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat()); + } } + public static class PositiveIntParam extends PositiveParam { - protected PositiveIntParam(String id) { super(id); } + protected PositiveIntParam(final String id) + { + super(id); + } + @Override - public Value decode(Tag tag, Level level) { return new NumericValue(((IntTag)tag).getAsInt()); } + public Value decode(final Tag tag, final Level level) + { + return new NumericValue(((IntTag) tag).getAsInt()); + } + @Override - public Tag toTag(Value value) { return IntTag.valueOf(NumericValue.asNumber(value, id).getInt()); } + public Tag toTag(final Value value) + { + return IntTag.valueOf(NumericValue.asNumber(value, id).getInt()); + } } + public static class NonNegativeIntParam extends NumericParam { - protected NonNegativeIntParam(String id) { super(id); } - @Override - public Value decode(Tag tag, Level level) { return new NumericValue(((IntTag)tag).getAsInt()); } - @Override - public Tag toTag(Value value) { return IntTag.valueOf(NumericValue.asNumber(value, id).getInt()); } - @Override public Value validate(Map options, MinecraftServer server, Value value) + protected NonNegativeIntParam(final String id) { - Value ret = super.validate(options, server, value); - if (((NumericValue)ret).getDouble()<0) throw new InternalExpressionException("'"+id+"' should be non-negative"); + super(id); + } + + @Override + public Value decode(final Tag tag, final Level level) + { + return new NumericValue(((IntTag) tag).getAsInt()); + } + + @Override + public Tag toTag(final Value value) + { + return IntTag.valueOf(NumericValue.asNumber(value, id).getInt()); + } + + @Override + public Value validate(final Map options, final MinecraftServer server, final Value value) + { + final Value ret = super.validate(options, server, value); + if (((NumericValue) ret).getDouble() < 0) + { + throw new InternalExpressionException("'" + id + "' should be non-negative"); + } return ret; } } + public static class NonNegativeFloatParam extends NumericParam { - protected NonNegativeFloatParam(String id) { super(id); } - @Override - public Value decode(Tag tag, Level level) { return new NumericValue(((FloatTag)tag).getAsFloat()); } - @Override - public Tag toTag(Value value) { return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat()); } - @Override public Value validate(Map options, MinecraftServer server, Value value) + protected NonNegativeFloatParam(final String id) { - Value ret = super.validate(options, server, value); - if (((NumericValue)ret).getDouble()<0) throw new InternalExpressionException("'"+id+"' should be non-negative"); + super(id); + } + + @Override + public Value decode(final Tag tag, final Level level) + { + return new NumericValue(((FloatTag) tag).getAsFloat()); + } + + @Override + public Tag toTag(final Value value) + { + return FloatTag.valueOf(NumericValue.asNumber(value, id).getFloat()); + } + + @Override + public Value validate(final Map options, final MinecraftServer server, final Value value) + { + final Value ret = super.validate(options, server, value); + if (((NumericValue) ret).getDouble() < 0) + { + throw new InternalExpressionException("'" + id + "' should be non-negative"); + } return ret; } } - - public static class Vec3Param extends Param { - private boolean roundsUpForBlocks; - protected Vec3Param(String id, boolean doesRoundUpForBlocks) + private final boolean roundsUpForBlocks; + + protected Vec3Param(final String id, final boolean doesRoundUpForBlocks) { super(id); roundsUpForBlocks = doesRoundUpForBlocks; } + @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) { return validate(this, options, value, roundsUpForBlocks); } - public static Value validate(Param p, Map options, Value value, boolean roundsUp) + + public static Value validate(final Param p, final Map options, final Value value, final boolean roundsUp) { - if (value instanceof BlockValue) + if (value instanceof final BlockValue bv) { if (options.containsKey("follow")) - throw new InternalExpressionException(p.id+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present"); - BlockPos pos = ((BlockValue) value).getPos(); - int offset = roundsUp?1:0; + { + throw new InternalExpressionException(p.id + " parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present"); + } + final BlockPos pos = bv.getPos(); + final int offset = roundsUp ? 1 : 0; return ListValue.of( - new NumericValue(pos.getX()+offset), - new NumericValue(pos.getY()+offset), - new NumericValue(pos.getZ()+offset) + new NumericValue(pos.getX() + offset), + new NumericValue(pos.getY() + offset), + new NumericValue(pos.getZ() + offset) ); } - if (value instanceof ListValue) + if (value instanceof final ListValue list) { - List values = ((ListValue) value).getItems(); - if (values.size()!=3) throw new InternalExpressionException("'"+p.id+"' requires 3 numerical values"); - for (Value component : values) + final List values = list.getItems(); + if (values.size() != 3) + { + throw new InternalExpressionException("'" + p.id + "' requires 3 numerical values"); + } + for (final Value component : values) { if (!(component instanceof NumericValue)) - throw new InternalExpressionException("'"+p.id+"' requires 3 numerical values"); + { + throw new InternalExpressionException("'" + p.id + "' requires 3 numerical values"); + } } return value; } - if (value instanceof EntityValue) + if (value instanceof final EntityValue ev) { if (options.containsKey("follow")) - throw new InternalExpressionException(p.id+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present"); - Entity e = ((EntityValue) value).getEntity(); + { + throw new InternalExpressionException(p.id + " parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present"); + } + final Entity e = ev.getEntity(); return ListValue.of( new NumericValue(e.getX()), new NumericValue(e.getY()), new NumericValue(e.getZ()) ); } - CarpetSettings.LOG.error("Value: "+value.getString()); - throw new InternalExpressionException("'"+p.id+"' requires a triple, block or entity to indicate position"); + CarpetSettings.LOG.error("Value: " + value.getString()); + throw new InternalExpressionException("'" + p.id + "' requires a triple, block or entity to indicate position"); } @Override - public Value decode(Tag tag, Level level) + public Value decode(final Tag tag, final Level level) { - ListTag ctag = (ListTag)tag; + final ListTag ctag = (ListTag) tag; return ListValue.of( new NumericValue(ctag.getDouble(0)), new NumericValue(ctag.getDouble(1)), new NumericValue(ctag.getDouble(2)) ); } + @Override - public Tag toTag(Value value) + public Tag toTag(final Value value) { - List lv = ((ListValue)value).getItems(); - ListTag tag = new ListTag(); + final List lv = ((ListValue) value).getItems(); + final ListTag tag = new ListTag(); tag.add(DoubleTag.valueOf(NumericValue.asNumber(lv.get(0), "x").getDouble())); tag.add(DoubleTag.valueOf(NumericValue.asNumber(lv.get(1), "y").getDouble())); tag.add(DoubleTag.valueOf(NumericValue.asNumber(lv.get(2), "z").getDouble())); @@ -1602,29 +2051,34 @@ public class ShapeDispatcher public static class PointsParam extends Param { - public PointsParam(String id) + public PointsParam(final String id) { super(id); } + @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) { - if (!(value instanceof ListValue)) - throw new InternalExpressionException(id+ " parameter should be a list"); - List points = new ArrayList<>(); - for (Value point: ((ListValue) value).getItems()) + if (!(value instanceof final ListValue list)) + { + throw new InternalExpressionException(id + " parameter should be a list"); + } + final List points = new ArrayList<>(); + for (final Value point : list.getItems()) + { points.add(Vec3Param.validate(this, options, point, false)); + } return ListValue.wrap(points); } @Override - public Value decode(Tag tag, Level level) + public Value decode(final Tag tag, final Level level) { - ListTag ltag = (ListTag)tag; - List points = new ArrayList<>(); - for (int i=0, ll = ltag.size(); i points = new ArrayList<>(); + for (int i = 0, ll = ltag.size(); i < ll; i++) { - ListTag ptag = ltag.getList(i); + final ListTag ptag = ltag.getList(i); points.add(ListValue.of( new NumericValue(ptag.getDouble(0)), new NumericValue(ptag.getDouble(1)), @@ -1633,15 +2087,16 @@ public class ShapeDispatcher } return ListValue.wrap(points); } + @Override - public Tag toTag(Value pointsValue) + public Tag toTag(final Value pointsValue) { - List lv = ((ListValue)pointsValue).getItems(); - ListTag ltag = new ListTag(); - for (Value value : lv) + final List lv = ((ListValue) pointsValue).getItems(); + final ListTag ltag = new ListTag(); + for (final Value value : lv) { - List coords = ((ListValue)value).getItems(); - ListTag tag = new ListTag(); + final List coords = ((ListValue) value).getItems(); + final ListTag tag = new ListTag(); tag.add(DoubleTag.valueOf(NumericValue.asNumber(coords.get(0), "x").getDouble())); tag.add(DoubleTag.valueOf(NumericValue.asNumber(coords.get(1), "y").getDouble())); tag.add(DoubleTag.valueOf(NumericValue.asNumber(coords.get(2), "z").getDouble())); @@ -1654,125 +2109,151 @@ public class ShapeDispatcher public static class ColorParam extends NumericParam { - protected ColorParam(String id) + protected ColorParam(final String id) { super(id); } @Override - public Value decode(Tag tag, Level level) { return new NumericValue(((IntTag)tag).getAsInt()); } + public Value decode(final Tag tag, final Level level) + { + return new NumericValue(((IntTag) tag).getAsInt()); + } + @Override - public Tag toTag(Value value) { return IntTag.valueOf(NumericValue.asNumber(value, id).getInt()); } + public Tag toTag(final Value value) + { + return IntTag.valueOf(NumericValue.asNumber(value, id).getInt()); + } } public static class EntityParam extends Param { - protected EntityParam(String id) { super(id); } + protected EntityParam(final String id) + { + super(id); + } @Override - public Tag toTag(Value value) + public Tag toTag(final Value value) { return IntTag.valueOf(NumericValue.asNumber(value, id).getInt()); } @Override - public Value validate(Map options, MinecraftServer server, Value value) + public Value validate(final Map options, final MinecraftServer server, final Value value) { - if (value instanceof EntityValue) return new NumericValue(((EntityValue) value).getEntity().getId()); - ServerPlayer player = EntityValue.getPlayerByValue(server, value); + if (value instanceof final EntityValue ev) + { + return new NumericValue(ev.getEntity().getId()); + } + final ServerPlayer player = EntityValue.getPlayerByValue(server, value); if (player == null) - throw new InternalExpressionException(id+" parameter needs to represent an entity or player"); + { + throw new InternalExpressionException(id + " parameter needs to represent an entity or player"); + } return new NumericValue(player.getId()); } @Override - public Value decode(Tag tag, Level level) { return new NumericValue(((IntTag)tag).getAsInt()); } + public Value decode(final Tag tag, final Level level) + { + return new NumericValue(((IntTag) tag).getAsInt()); + } } - private static boolean isStraight(Vec3 from, Vec3 to, double density) + private static boolean isStraight(final Vec3 from, final Vec3 to, final double density) { - if ( (from.x == to.x && from.y == to.y) || (from.x == to.x && from.z == to.z) || (from.y == to.y && from.z == to.z)) + if ((from.x == to.x && from.y == to.y) || (from.x == to.x && from.z == to.z) || (from.y == to.y && from.z == to.z)) + { return from.distanceTo(to) / density > 20; + } return false; } - private static int drawOptimizedParticleLine(List playerList, ParticleOptions particle, Vec3 from, Vec3 to, double density) + private static int drawOptimizedParticleLine(final List playerList, final ParticleOptions particle, final Vec3 from, final Vec3 to, final double density) { - double distance = from.distanceTo(to); - int particles = (int)(distance/density); - Vec3 towards = to.subtract(from); + final double distance = from.distanceTo(to); + final int particles = (int) (distance / density); + final Vec3 towards = to.subtract(from); int parts = 0; - for (ServerPlayer player : playerList) + for (final ServerPlayer player : playerList) { - ServerLevel world = player.getLevel(); + final ServerLevel world = player.getLevel(); world.sendParticles(player, particle, true, - (towards.x)/2+from.x, (towards.y)/2+from.y, (towards.z)/2+from.z, particles/3, - towards.x/6, towards.y/6, towards.z/6, 0.0); + (towards.x) / 2 + from.x, (towards.y) / 2 + from.y, (towards.z) / 2 + from.z, particles / 3, + towards.x / 6, towards.y / 6, towards.z / 6, 0.0); world.sendParticles(player, particle, true, - from.x, from.y, from.z,1,0.0,0.0,0.0,0.0); + from.x, from.y, from.z, 1, 0.0, 0.0, 0.0, 0.0); world.sendParticles(player, particle, true, - to.x, to.y, to.z,1,0.0,0.0,0.0,0.0); - parts += particles/3+2; + to.x, to.y, to.z, 1, 0.0, 0.0, 0.0, 0.0); + parts += particles / 3 + 2; } int divider = 6; - while (particles/divider > 1) + while (particles / divider > 1) { - int center = (divider*2)/3; - int dev = 2*divider; - for (ServerPlayer player : playerList) + final int center = (divider * 2) / 3; + final int dev = 2 * divider; + for (final ServerPlayer player : playerList) { - ServerLevel world = player.getLevel(); + final ServerLevel world = player.getLevel(); world.sendParticles(player, particle, true, - (towards.x)/center+from.x, (towards.y)/center+from.y, (towards.z)/center+from.z, particles/divider, - towards.x/dev, towards.y/dev, towards.z/dev, 0.0); + (towards.x) / center + from.x, (towards.y) / center + from.y, (towards.z) / center + from.z, particles / divider, + towards.x / dev, towards.y / dev, towards.z / dev, 0.0); world.sendParticles(player, particle, true, - (towards.x)*(1.0-1.0/center)+from.x, (towards.y)*(1.0-1.0/center)+from.y, (towards.z)*(1.0-1.0/center)+from.z, particles/divider, - towards.x/dev, towards.y/dev, towards.z/dev, 0.0); + (towards.x) * (1.0 - 1.0 / center) + from.x, (towards.y) * (1.0 - 1.0 / center) + from.y, (towards.z) * (1.0 - 1.0 / center) + from.z, particles / divider, + towards.x / dev, towards.y / dev, towards.z / dev, 0.0); } - parts += 2*particles/divider; - divider = 2*divider; + parts += 2 * particles / divider; + divider = 2 * divider; } return parts; } - public static int drawParticleLine(List players, ParticleOptions particle, Vec3 from, Vec3 to, double density) + public static int drawParticleLine(final List players, final ParticleOptions particle, final Vec3 from, final Vec3 to, final double density) { - double distance = from.distanceToSqr(to); - if (distance == 0) return 0; + final double distance = from.distanceToSqr(to); + if (distance == 0) + { + return 0; + } int pcount = 0; if (distance < 100) { - RandomSource rand = players.get(0).level.random; - int particles = (int)(distance/density)+1; - Vec3 towards = to.subtract(from); + final RandomSource rand = players.get(0).level.random; + final int particles = (int) (distance / density) + 1; + final Vec3 towards = to.subtract(from); for (int i = 0; i < particles; i++) { - Vec3 at = from.add(towards.scale( rand.nextDouble())); - for (ServerPlayer player : players) + final Vec3 at = from.add(towards.scale(rand.nextDouble())); + for (final ServerPlayer player : players) { player.getLevel().sendParticles(player, particle, true, at.x, at.y, at.z, 1, 0.0, 0.0, 0.0, 0.0); - pcount ++; + pcount++; } } return pcount; } - if (isStraight(from, to, density)) return drawOptimizedParticleLine(players, particle, from, to, density); - Vec3 incvec = to.subtract(from).scale(2*density/Math.sqrt(distance)); + if (isStraight(from, to, density)) + { + return drawOptimizedParticleLine(players, particle, from, to, density); + } + final Vec3 incvec = to.subtract(from).scale(2 * density / Math.sqrt(distance)); - for (Vec3 delta = new Vec3(0.0,0.0,0.0); - delta.lengthSqr(), Long2ObjectOpenHashMap>> shapes; private final Map, Long2ObjectOpenHashMap>> labels; - private Minecraft client; + private final Minecraft client; - private Map>> renderedShapes - = new HashMap<>() {{ + private final Map>> renderedShapes + = new HashMap<>() + {{ put("line", RenderedLine::new); put("box", RenderedBox::new); put("sphere", RenderedSphere::new); @@ -71,22 +73,25 @@ public class ShapesRenderer put("item", (c, s) -> new RenderedSprite(c, s, true)); }}; - public ShapesRenderer(Minecraft minecraftClient) + public ShapesRenderer(final Minecraft minecraftClient) { this.client = minecraftClient; shapes = new HashMap<>(); labels = new HashMap<>(); } - public void render(PoseStack matrices, Camera camera, float partialTick) + public void render(final PoseStack matrices, final Camera camera, final float partialTick) { - CarpetProfiler.ProfilerToken token = CarpetProfiler.start_section(null, "Scarpet client", CarpetProfiler.TYPE.GENERAL); + final CarpetProfiler.ProfilerToken token = CarpetProfiler.start_section(null, "Scarpet client", CarpetProfiler.TYPE.GENERAL); //Camera camera = this.client.gameRenderer.getCamera(); - ClientLevel iWorld = this.client.level; - ResourceKey dimensionType = iWorld.dimension(); + final ClientLevel iWorld = this.client.level; + final ResourceKey dimensionType = iWorld.dimension(); if ((shapes.get(dimensionType) == null || shapes.get(dimensionType).isEmpty()) && - (labels.get(dimensionType) == null || labels.get(dimensionType).isEmpty())) return; - long currentTime = client.level.getGameTime(); + (labels.get(dimensionType) == null || labels.get(dimensionType).isEmpty())) + { + return; + } + final long currentTime = client.level.getGameTime(); RenderSystem.enableDepthTest(); RenderSystem.setShader(GameRenderer::getPositionColorShader); RenderSystem.depthFunc(515); @@ -102,45 +107,56 @@ public class ShapesRenderer //RenderSystem.polygonOffset(-3f, -3f); //RenderSystem.enablePolygonOffset(); - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuilder(); + final Tesselator tessellator = Tesselator.getInstance(); + final BufferBuilder bufferBuilder = tessellator.getBuilder(); // render - double cameraX = camera.getPosition().x; - double cameraY = camera.getPosition().y; - double cameraZ = camera.getPosition().z; - boolean entityBoxes = client.getEntityRenderDispatcher().shouldRenderHitBoxes(); + final double cameraX = camera.getPosition().x; + final double cameraY = camera.getPosition().y; + final double cameraZ = camera.getPosition().z; + final boolean entityBoxes = client.getEntityRenderDispatcher().shouldRenderHitBoxes(); - if (shapes.size() != 0) { + if (shapes.size() != 0) + { shapes.get(dimensionType).long2ObjectEntrySet().removeIf( entry -> entry.getValue().isExpired(currentTime) ); - PoseStack matrixStack = RenderSystem.getModelViewStack(); + final PoseStack matrixStack = RenderSystem.getModelViewStack(); matrixStack.pushPose(); matrixStack.mulPoseMatrix(matrices.last().pose()); RenderSystem.applyModelViewMatrix(); // lines RenderSystem.lineWidth(0.5F); - shapes.get(dimensionType).values().forEach( s -> { - if ( (!s.shape.debug ||entityBoxes ) && s.shouldRender(dimensionType)) s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); + shapes.get(dimensionType).values().forEach(s -> { + if ((!s.shape.debug || entityBoxes) && s.shouldRender(dimensionType)) + { + s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); + } }); // faces RenderSystem.lineWidth(0.1F); shapes.get(dimensionType).values().forEach(s -> { - if ( (!s.shape.debug ||entityBoxes ) && s.shouldRender(dimensionType)) s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); + if ((!s.shape.debug || entityBoxes) && s.shouldRender(dimensionType)) + { + s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); + } }); RenderSystem.lineWidth(1.0F); matrixStack.popPose(); RenderSystem.applyModelViewMatrix(); } - if (labels.size() != 0) { + if (labels.size() != 0) + { labels.get(dimensionType).long2ObjectEntrySet().removeIf( entry -> entry.getValue().isExpired(currentTime) ); labels.get(dimensionType).values().forEach(s -> { - if ( (!s.shape.debug || entityBoxes) && s.shouldRender(dimensionType)) s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); + if ((!s.shape.debug || entityBoxes) && s.shouldRender(dimensionType)) + { + s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); + } }); } RenderSystem.enableCull(); @@ -150,34 +166,37 @@ public class ShapesRenderer CarpetProfiler.end_current_section(token); } - public void addShapes(ListTag tag) + public void addShapes(final ListTag tag) { - CarpetProfiler.ProfilerToken token = CarpetProfiler.start_section(null, "Scarpet client", CarpetProfiler.TYPE.GENERAL); - for (int i=0, count = tag.size(); i < count; i++) + final CarpetProfiler.ProfilerToken token = CarpetProfiler.start_section(null, "Scarpet client", CarpetProfiler.TYPE.GENERAL); + for (int i = 0, count = tag.size(); i < count; i++) { addShape(tag.getCompound(i)); } CarpetProfiler.end_current_section(token); } - public void addShape(CompoundTag tag) + public void addShape(final CompoundTag tag) { - ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.fromTag(tag, client.level); - if (shape == null) return; - BiFunction> shapeFactory; + final ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.fromTag(tag, client.level); + if (shape == null) + { + return; + } + final BiFunction> shapeFactory; shapeFactory = renderedShapes.get(tag.getString("shape")); if (shapeFactory == null) { - CarpetSettings.LOG.info("Unrecognized shape: "+tag.getString("shape")); + CarpetSettings.LOG.info("Unrecognized shape: " + tag.getString("shape")); } else { - RenderedShape rshape = shapeFactory.apply(client, shape); - ResourceKey dim = shape.shapeDimension; - long key = rshape.key(); - Map, Long2ObjectOpenHashMap>> container = - rshape.stageDeux()?labels:shapes; - RenderedShape existing = container.computeIfAbsent(dim, d -> new Long2ObjectOpenHashMap<>()).get(key); + final RenderedShape rshape = shapeFactory.apply(client, shape); + final ResourceKey dim = shape.shapeDimension; + final long key = rshape.key(); + final Map, Long2ObjectOpenHashMap>> container = + rshape.stageDeux() ? labels : shapes; + final RenderedShape existing = container.computeIfAbsent(dim, d -> new Long2ObjectOpenHashMap<>()).get(key); if (existing != null) { // promoting previous shape existing.promoteWith(rshape); @@ -189,6 +208,7 @@ public class ShapesRenderer } } + public void reset() { shapes.values().forEach(Long2ObjectOpenHashMap::clear); @@ -197,7 +217,7 @@ public class ShapesRenderer public void renewShapes() { - CarpetProfiler.ProfilerToken token = CarpetProfiler.start_section(null, "Scarpet client", CarpetProfiler.TYPE.GENERAL); + final CarpetProfiler.ProfilerToken token = CarpetProfiler.start_section(null, "Scarpet client", CarpetProfiler.TYPE.GENERAL); shapes.values().forEach(el -> el.values().forEach(shape -> shape.expiryTick++)); labels.values().forEach(el -> el.values().forEach(shape -> shape.expiryTick++)); @@ -210,43 +230,61 @@ public class ShapesRenderer protected Minecraft client; long expiryTick; double renderEpsilon = 0; - public abstract void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder builder, double cx, double cy, double cz, float partialTick ); - public void renderFaces(Tesselator tessellator, BufferBuilder builder, double cx, double cy, double cz, float partialTick ) {} - protected RenderedShape(Minecraft client, T shape) + + public abstract void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder builder, double cx, double cy, double cz, float partialTick); + + public void renderFaces(final Tesselator tessellator, final BufferBuilder builder, final double cx, final double cy, final double cz, final float partialTick) + { + } + + protected RenderedShape(final Minecraft client, final T shape) { this.shape = shape; this.client = client; - expiryTick = client.level.getGameTime()+shape.getExpiry(); - renderEpsilon = (3+((double)key())/Long.MAX_VALUE)/1000; + expiryTick = client.level.getGameTime() + shape.getExpiry(); + renderEpsilon = (3 + ((double) key()) / Long.MAX_VALUE) / 1000; } - public boolean isExpired(long currentTick) + public boolean isExpired(final long currentTick) { - return expiryTick < currentTick; + return expiryTick < currentTick; } + public long key() { return shape.key(client.level.registryAccess()); - }; - public boolean shouldRender(ResourceKey dim) + } + + public boolean shouldRender(final ResourceKey dim) { - if (shape.followEntity <=0 ) return true; - if (client.level == null) return false; - if (client.level.dimension() != dim) return false; + if (shape.followEntity <= 0) + { + return true; + } + if (client.level == null) + { + return false; + } + if (client.level.dimension() != dim) + { + return false; + } return client.level.getEntity(shape.followEntity) != null; } + public boolean stageDeux() { return false; } - public void promoteWith(RenderedShape rshape) + public void promoteWith(final RenderedShape rshape) { expiryTick = rshape.expiryTick; } } - public static class RenderedSprite extends RenderedShape { + public static class RenderedSprite extends RenderedShape + { private final boolean isitem; private ItemTransforms.TransformType transformType = ItemTransforms.TransformType.NONE; @@ -255,23 +293,27 @@ public class ShapesRenderer private BlockState blockState; private BlockEntity BlockEntity = null; - protected RenderedSprite(Minecraft client, ShapeDispatcher.ExpiringShape shape, boolean isitem) { + protected RenderedSprite(final Minecraft client, final ShapeDispatcher.ExpiringShape shape, final boolean isitem) + { super(client, (ShapeDispatcher.DisplayedSprite) shape); this.isitem = isitem; - if (isitem) { + if (isitem) + { this.transformType = ItemTransforms.TransformType.valueOf(((ShapeDispatcher.DisplayedSprite) shape).itemTransformType.toUpperCase(Locale.ROOT)); } } @Override - public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder builder, double cx, double cy, - double cz, float partialTick) + public void renderLines(final PoseStack matrices, final Tesselator tessellator, final BufferBuilder builder, final double cx, final double cy, + final double cz, final float partialTick) { if (shape.a == 0.0) + { return; + } - Vec3 v1 = shape.relativiseRender(client.level, shape.pos, partialTick); - Camera camera1 = client.gameRenderer.getMainCamera(); + final Vec3 v1 = shape.relativiseRender(client.level, shape.pos, partialTick); + final Camera camera1 = client.gameRenderer.getMainCamera(); matrices.pushPose(); if (!isitem)// blocks should use its center as the origin @@ -281,9 +323,18 @@ public class ShapesRenderer matrices.translate(v1.x - cx, v1.y - cy, v1.z - cz); ShapeDirection.rotatePoseStackByShapeDirection(matrices, shape.facing, camera1, isitem ? v1 : v1.add(0.5, 0.5, 0.5)); - if (shape.tilt != 0.0f) matrices.mulPose(Axis.ZP.rotationDegrees(-shape.tilt)); - if (shape.lean != 0.0f) matrices.mulPose(Axis.XP.rotationDegrees(-shape.lean)); - if (shape.turn != 0.0f) matrices.mulPose(Axis.YP.rotationDegrees( shape.turn)); + if (shape.tilt != 0.0f) + { + matrices.mulPose(Axis.ZP.rotationDegrees(-shape.tilt)); + } + if (shape.lean != 0.0f) + { + matrices.mulPose(Axis.XP.rotationDegrees(-shape.lean)); + } + if (shape.turn != 0.0f) + { + matrices.mulPose(Axis.YP.rotationDegrees(shape.turn)); + } matrices.scale(shape.scaleX, shape.scaleY, shape.scaleZ); if (!isitem) @@ -291,7 +342,8 @@ public class ShapesRenderer // blocks should use its center as the origin matrices.translate(-0.5, -0.5, -0.5); } - else { + else + { // items seems to be flipped by default matrices.mulPose(Axis.YP.rotationDegrees(180)); } @@ -302,7 +354,8 @@ public class ShapesRenderer blockPos = new BlockPos(v1); int light = 0; - if (client.level != null) { + if (client.level != null) + { light = LightTexture.pack( shape.blockLight < 0 ? client.level.getBrightness(LightLayer.BLOCK, blockPos) : shape.blockLight, shape.skyLight < 0 ? client.level.getBrightness(LightLayer.SKY, blockPos) : shape.skyLight @@ -311,18 +364,20 @@ public class ShapesRenderer blockState = shape.blockState; - MultiBufferSource.BufferSource immediate = client.renderBuffers().bufferSource(); - if (!isitem) { + final MultiBufferSource.BufferSource immediate = client.renderBuffers().bufferSource(); + if (!isitem) + { // draw the block itself - if (blockState.getRenderShape() == RenderShape.MODEL) { + if (blockState.getRenderShape() == RenderShape.MODEL) + { - var bakedModel = client.getBlockRenderer().getBlockModel(blockState); - int color = client.getBlockColors().getColor(blockState,client.level,blockPos,0); + final var bakedModel = client.getBlockRenderer().getBlockModel(blockState); + final int color = client.getBlockColors().getColor(blockState, client.level, blockPos, 0); //dont know why there is a 0. //see https://github.com/senseiwells/EssentialClient/blob/4db1f291936f502304791ee323f369c206b3021d/src/main/java/me/senseiwells/essentialclient/utils/render/RenderHelper.java#L464 - float red = (color >> 16 & 0xFF) / 255.0F; - float green = (color >> 8 & 0xFF) / 255.0F; - float blue = (color & 0xFF) / 255.0F; + final float red = (color >> 16 & 0xFF) / 255.0F; + final float green = (color >> 8 & 0xFF) / 255.0F; + final float blue = (color & 0xFF) / 255.0F; client.getBlockRenderer().getModelRenderer().renderModel(matrices.last(), immediate.getBuffer(ItemBlockRenderTypes.getRenderType(blockState, false)), blockState, bakedModel, red, green, blue, light, OverlayTexture.NO_OVERLAY); } @@ -335,21 +390,25 @@ public class ShapesRenderer if (BlockEntity != null) { BlockEntity.setLevel(client.level); - if (shape.blockEntity != null) BlockEntity.load(shape.blockEntity); + if (shape.blockEntity != null) + { + BlockEntity.load(shape.blockEntity); + } } } } if (BlockEntity instanceof ShulkerBoxBlockEntity sbBlockEntity) { sbrender(sbBlockEntity, partialTick, - matrices, immediate, light, OverlayTexture.NO_OVERLAY); + matrices, immediate, light, OverlayTexture.NO_OVERLAY); } else { if (BlockEntity != null) { final BlockEntityRenderer blockEntityRenderer = client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity); - if (blockEntityRenderer != null) { + if (blockEntityRenderer != null) + { blockEntityRenderer.render(BlockEntity, partialTick, matrices, immediate, light, OverlayTexture.NO_OVERLAY); @@ -375,24 +434,25 @@ public class ShapesRenderer } @Override - public boolean stageDeux() { + public boolean stageDeux() + { return true; } // copy and modifiy a bit from net.minecraft.client.renderer.blockentity.ShulkerBoxRenderer.render - public void sbrender(ShulkerBoxBlockEntity shulkerBoxBlockEntity, float f, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int j) + public void sbrender(final ShulkerBoxBlockEntity shulkerBoxBlockEntity, final float f, final PoseStack poseStack, final MultiBufferSource multiBufferSource, final int i, final int j) { Direction direction = Direction.UP; if (shulkerBoxBlockEntity.hasLevel()) { - BlockState blockState = shulkerBoxBlockEntity.getBlockState(); + final BlockState blockState = shulkerBoxBlockEntity.getBlockState(); if (blockState.getBlock() instanceof ShulkerBoxBlock) { direction = blockState.getValue(ShulkerBoxBlock.FACING); } } - DyeColor dyeColor = shulkerBoxBlockEntity.getColor(); - Material material; + final DyeColor dyeColor = shulkerBoxBlockEntity.getColor(); + final Material material; if (dyeColor == null) { material = Sheets.DEFAULT_SHULKER_TEXTURE_LOCATION; @@ -401,18 +461,18 @@ public class ShapesRenderer { material = Sheets.SHULKER_TEXTURE_LOCATION.get(dyeColor.getId()); } - + poseStack.pushPose(); poseStack.translate(0.5, 0.5, 0.5); poseStack.scale(0.9995F, 0.9995F, 0.9995F); poseStack.mulPose(direction.getRotation()); poseStack.scale(1.0F, -1.0F, -1.0F); poseStack.translate(0.0, -1.0, 0.0); - ShulkerModel model = ((ShulkerBoxAccessMixin) client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity)).getModel(); - ModelPart modelPart = model.getLid(); + final ShulkerModel model = ((ShulkerBoxAccessMixin) client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity)).getModel(); + final ModelPart modelPart = model.getLid(); modelPart.setPos(0.0F, 24.0F - shulkerBoxBlockEntity.getProgress(f) * 0.5F * 16.0F, 0.0F); modelPart.yRot = 270.0F * shulkerBoxBlockEntity.getProgress(f) * (float) (Math.PI / 180.0); - VertexConsumer vertexConsumer = material.buffer(multiBufferSource, RenderType::entityCutoutNoCull); + final VertexConsumer vertexConsumer = material.buffer(multiBufferSource, RenderType::entityCutoutNoCull); model.renderToBuffer(poseStack, vertexConsumer, i, j, 1.0F, 1.0F, 1.0F, 1.0F); poseStack.popPose(); } @@ -422,33 +482,49 @@ public class ShapesRenderer public static class RenderedText extends RenderedShape { - protected RenderedText(Minecraft client, ShapeDispatcher.ExpiringShape shape) + protected RenderedText(final Minecraft client, final ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.DisplayedText)shape); + super(client, (ShapeDispatcher.DisplayedText) shape); } @Override - public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder builder, double cx, double cy, double cz, float partialTick) + public void renderLines(final PoseStack matrices, final Tesselator tessellator, final BufferBuilder builder, final double cx, final double cy, final double cz, final float partialTick) { - if (shape.a == 0.0) return; - Vec3 v1 = shape.relativiseRender(client.level, shape.pos, partialTick); - Camera camera1 = client.gameRenderer.getMainCamera(); - Font textRenderer = client.font; + if (shape.a == 0.0) + { + return; + } + final Vec3 v1 = shape.relativiseRender(client.level, shape.pos, partialTick); + final Camera camera1 = client.gameRenderer.getMainCamera(); + final Font textRenderer = client.font; if (shape.doublesided) + { RenderSystem.disableCull(); + } else + { RenderSystem.enableCull(); + } matrices.pushPose(); - matrices.translate(v1.x - cx,v1.y - cy,v1.z - cz); + matrices.translate(v1.x - cx, v1.y - cy, v1.z - cz); ShapeDirection.rotatePoseStackByShapeDirection(matrices, shape.facing, camera1, v1); - matrices.scale(shape.size* 0.0025f, -shape.size*0.0025f, shape.size*0.0025f); + matrices.scale(shape.size * 0.0025f, -shape.size * 0.0025f, shape.size * 0.0025f); //RenderSystem.scalef(shape.size* 0.0025f, -shape.size*0.0025f, shape.size*0.0025f); - if (shape.tilt!=0.0f) matrices.mulPose(Axis.ZP.rotationDegrees(shape.tilt)); - if (shape.lean!=0.0f) matrices.mulPose(Axis.XP.rotationDegrees(shape.lean)); - if (shape.turn!=0.0f) matrices.mulPose(Axis.YP.rotationDegrees(shape.turn)); - matrices.translate(-10*shape.indent, -10*shape.height-9, (-10*renderEpsilon)-10*shape.raise); + if (shape.tilt != 0.0f) + { + matrices.mulPose(Axis.ZP.rotationDegrees(shape.tilt)); + } + if (shape.lean != 0.0f) + { + matrices.mulPose(Axis.XP.rotationDegrees(shape.lean)); + } + if (shape.turn != 0.0f) + { + matrices.mulPose(Axis.YP.rotationDegrees(shape.turn)); + } + matrices.translate(-10 * shape.indent, -10 * shape.height - 9, (-10 * renderEpsilon) - 10 * shape.raise); //if (visibleThroughWalls) RenderSystem.disableDepthTest(); matrices.scale(-1, 1, 1); //RenderSystem.applyModelViewMatrix(); // passed matrix directly to textRenderer.draw, not AffineTransformation.identity().getMatrix(), @@ -456,13 +532,13 @@ public class ShapesRenderer float text_x = 0; if (shape.align == 0) { - text_x = (float)(-textRenderer.width(shape.value.getString())) / 2.0F; + text_x = (float) (-textRenderer.width(shape.value.getString())) / 2.0F; } else if (shape.align == 1) { - text_x = (float)(-textRenderer.width(shape.value.getString())); + text_x = (float) (-textRenderer.width(shape.value.getString())); } - MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(builder); + final MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(builder); textRenderer.drawInBatch(shape.value, text_x, 0.0F, shape.textcolor, false, matrices.last().pose(), immediate, false, shape.textbck, 15728880); immediate.endBatch(); matrices.popPose(); @@ -476,16 +552,16 @@ public class ShapesRenderer } @Override - public void promoteWith(RenderedShape rshape) + public void promoteWith(final RenderedShape rshape) { super.promoteWith(rshape); try { this.shape.value = ((ShapeDispatcher.DisplayedText) rshape.shape).value; } - catch (ClassCastException ignored) + catch (final ClassCastException ignored) { - CarpetSettings.LOG.error("shape "+rshape.shape.getClass()+" cannot cast to a Label"); + CarpetSettings.LOG.error("shape " + rshape.shape.getClass() + " cannot cast to a Label"); } } } @@ -493,251 +569,312 @@ public class ShapesRenderer public static class RenderedBox extends RenderedShape { - private RenderedBox(Minecraft client, ShapeDispatcher.ExpiringShape shape) + private RenderedBox(final Minecraft client, final ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.Box)shape); - + super(client, (ShapeDispatcher.Box) shape); } + @Override - public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + public void renderLines(final PoseStack matrices, final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) { - if (shape.a == 0.0) return; - Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick); - Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick); + if (shape.a == 0.0) + { + return; + } + final Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick); + final Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick); drawBoxWireGLLines(tessellator, bufferBuilder, - (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), - (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), - v1.x!=v2.x, v1.y!=v2.y, v1.z!=v2.z, + (float) (v1.x - cx - renderEpsilon), (float) (v1.y - cy - renderEpsilon), (float) (v1.z - cz - renderEpsilon), + (float) (v2.x - cx + renderEpsilon), (float) (v2.y - cy + renderEpsilon), (float) (v2.z - cz + renderEpsilon), + v1.x != v2.x, v1.y != v2.y, v1.z != v2.z, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b ); } + @Override - public void renderFaces(Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + public void renderFaces(final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) { - if (shape.fa == 0.0) return; - Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick); - Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick); + if (shape.fa == 0.0) + { + return; + } + final Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick); + final Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick); // consider using built-ins //DebugRenderer.drawBox(new Box(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z), 0.5f, 0.5f, 0.5f, 0.5f);//shape.r, shape.g, shape.b, shape.a); drawBoxFaces(tessellator, bufferBuilder, - (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), - (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), - v1.x!=v2.x, v1.y!=v2.y, v1.z!=v2.z, + (float) (v1.x - cx - renderEpsilon), (float) (v1.y - cy - renderEpsilon), (float) (v1.z - cz - renderEpsilon), + (float) (v2.x - cx + renderEpsilon), (float) (v2.y - cy + renderEpsilon), (float) (v2.z - cz + renderEpsilon), + v1.x != v2.x, v1.y != v2.y, v1.z != v2.z, shape.fr, shape.fg, shape.fb, shape.fa ); } - } public static class RenderedLine extends RenderedShape { - public RenderedLine(Minecraft client, ShapeDispatcher.ExpiringShape shape) + public RenderedLine(final Minecraft client, final ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.Line)shape); + super(client, (ShapeDispatcher.Line) shape); } + @Override - public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + public void renderLines(final PoseStack matrices, final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) { - Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick); - Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick); + final Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick); + final Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick); drawLine(tessellator, bufferBuilder, - (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), - (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), + (float) (v1.x - cx - renderEpsilon), (float) (v1.y - cy - renderEpsilon), (float) (v1.z - cz - renderEpsilon), + (float) (v2.x - cx + renderEpsilon), (float) (v2.y - cy + renderEpsilon), (float) (v2.z - cz + renderEpsilon), shape.r, shape.g, shape.b, shape.a ); } } + public static class RenderedPolyface extends RenderedShape { private static final VertexFormat.Mode[] faceIndices = new VertexFormat.Mode[]{ Mode.LINES, Mode.LINE_STRIP, Mode.DEBUG_LINES, Mode.DEBUG_LINE_STRIP, Mode.TRIANGLES, Mode.TRIANGLE_STRIP, Mode.TRIANGLE_FAN, Mode.QUADS}; - public RenderedPolyface(Minecraft client, ShapeDispatcher.ExpiringShape shape) + public RenderedPolyface(final Minecraft client, final ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.Polyface)shape); + super(client, (ShapeDispatcher.Polyface) shape); } + @Override - public void renderFaces(Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) - { - if(shape.fa==0){return;} + public void renderFaces(final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) + { + if (shape.fa == 0) + { + return; + } if (shape.doublesided) + { RenderSystem.disableCull(); + } else + { RenderSystem.enableCull(); - + } + bufferBuilder.begin(faceIndices[shape.mode], DefaultVertexFormat.POSITION_COLOR); - for(int i=0;i0;i-=2){ - vec=shape.vertex_list.get(i); - if(shape.relative.get(i)){ - vec=shape.relativiseRender(client.level, vec, partialTick); - } - builder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); - } - if(shape.inneredges){ - for(i=2;i 0; i -= 2) + { + vec = shape.vertex_list.get(i); + if (shape.relative.get(i)) + { + vec = shape.relativiseRender(client.level, vec, partialTick); + } + builder.vertex(vec.x() - cx, vec.y() - cy, vec.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); + } + if (shape.inneredges) + { + for (i = 2; i < shape.vertex_list.size() - 1; i++) + { + vec = shape.vertex_list.get(i); + if (shape.relative.get(i)) + { + vec = shape.relativiseRender(client.level, vec, partialTick); + } + builder.vertex(vec.x() - cx, vec.y() - cy, vec.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); } } + tessellator.end(); + return; + } + if (shape.mode == 4) + { + builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); + for (int i = 0; i < shape.vertex_list.size(); i++) + { + Vec3 vecA = shape.vertex_list.get(i); + if (shape.relative.get(i)) + { + vecA = shape.relativiseRender(client.level, vecA, partialTick); + } + i++; + Vec3 vecB = shape.vertex_list.get(i); + if (shape.relative.get(i)) + { + vecB = shape.relativiseRender(client.level, vecB, partialTick); + } + i++; + Vec3 vecC = shape.vertex_list.get(i); + if (shape.relative.get(i)) + { + vecC = shape.relativiseRender(client.level, vecC, partialTick); + } + builder.vertex(vecA.x() - cx, vecA.y() - cy, vecA.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); + builder.vertex(vecB.x() - cx, vecB.y() - cy, vecB.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); + + builder.vertex(vecB.x() - cx, vecB.y() - cy, vecB.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); + builder.vertex(vecC.x() - cx, vecC.y() - cy, vecC.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); + + builder.vertex(vecC.x() - cx, vecC.y() - cy, vecC.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); + builder.vertex(vecA.x() - cx, vecA.y() - cy, vecA.z() - cz).color(shape.r, shape.g, shape.b, shape.a).endVertex(); + } + tessellator.end(); + } + } } + public static class RenderedSphere extends RenderedShape { - public RenderedSphere(Minecraft client, ShapeDispatcher.ExpiringShape shape) + public RenderedSphere(final Minecraft client, final ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.Sphere)shape); + super(client, (ShapeDispatcher.Sphere) shape); } + @Override - public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + public void renderLines(final PoseStack matrices, final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) { - if (shape.a == 0.0) return; - Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); + if (shape.a == 0.0) + { + return; + } + final Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); drawSphereWireframe(tessellator, bufferBuilder, - (float)(vc.x-cx), (float)(vc.y-cy), (float)(vc.z-cz), - (float)(shape.radius+renderEpsilon), shape.subdivisions, + (float) (vc.x - cx), (float) (vc.y - cy), (float) (vc.z - cz), + (float) (shape.radius + renderEpsilon), shape.subdivisions, shape.r, shape.g, shape.b, shape.a); } + @Override - public void renderFaces(Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + public void renderFaces(final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) { - if (shape.fa == 0.0) return; - Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); + if (shape.fa == 0.0) + { + return; + } + final Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); drawSphereFaces(tessellator, bufferBuilder, - (float)(vc.x-cx), (float)(vc.y-cy), (float)(vc.z-cz), - (float)(shape.radius+renderEpsilon), shape.subdivisions, + (float) (vc.x - cx), (float) (vc.y - cy), (float) (vc.z - cz), + (float) (shape.radius + renderEpsilon), shape.subdivisions, shape.fr, shape.fg, shape.fb, shape.fa); } } public static class RenderedCylinder extends RenderedShape { - public RenderedCylinder(Minecraft client, ShapeDispatcher.ExpiringShape shape) + public RenderedCylinder(final Minecraft client, final ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.Cylinder)shape); + super(client, (ShapeDispatcher.Cylinder) shape); } + @Override - public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + public void renderLines(final PoseStack matrices, final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) { - if (shape.a == 0.0) return; - Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); - double dir = Mth.sign(shape.height); + if (shape.a == 0.0) + { + return; + } + final Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); + final double dir = Mth.sign(shape.height); drawCylinderWireframe(tessellator, bufferBuilder, (float) (vc.x - cx - dir * renderEpsilon), (float) (vc.y - cy - dir * renderEpsilon), (float) (vc.z - cz - dir * renderEpsilon), - (float) (shape.radius + renderEpsilon), (float) (shape.height + 2*dir*renderEpsilon), shape.axis, + (float) (shape.radius + renderEpsilon), (float) (shape.height + 2 * dir * renderEpsilon), shape.axis, shape.subdivisions, shape.radius == 0, shape.r, shape.g, shape.b, shape.a); } + @Override - public void renderFaces(Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + public void renderFaces(final Tesselator tessellator, final BufferBuilder bufferBuilder, final double cx, final double cy, final double cz, final float partialTick) { - if (shape.fa == 0.0) return; - Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); - double dir = Mth.sign(shape.height); + if (shape.fa == 0.0) + { + return; + } + final Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick); + final double dir = Mth.sign(shape.height); drawCylinderFaces(tessellator, bufferBuilder, (float) (vc.x - cx - dir * renderEpsilon), (float) (vc.y - cy - dir * renderEpsilon), (float) (vc.z - cz - dir * renderEpsilon), - (float) (shape.radius + renderEpsilon), (float) (shape.height + 2*dir*renderEpsilon), shape.axis, + (float) (shape.radius + renderEpsilon), (float) (shape.height + 2 * dir * renderEpsilon), shape.axis, shape.subdivisions, shape.radius == 0, shape.fr, shape.fg, shape.fb, shape.fa); } @@ -745,7 +882,8 @@ public class ShapesRenderer // some raw shit - public static void drawLine(Tesselator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + public static void drawLine(final Tesselator tessellator, final BufferBuilder builder, final float x1, final float y1, final float z1, final float x2, final float y2, final float z2, final float red1, final float grn1, final float blu1, final float alpha) + { builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).endVertex(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).endVertex(); @@ -753,11 +891,11 @@ public class ShapesRenderer } public static void drawBoxWireGLLines( - Tesselator tessellator, BufferBuilder builder, - float x1, float y1, float z1, - float x2, float y2, float z2, - boolean xthick, boolean ythick, boolean zthick, - float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) + final Tesselator tessellator, final BufferBuilder builder, + final float x1, final float y1, final float z1, + final float x2, final float y2, final float z2, + final boolean xthick, final boolean ythick, final boolean zthick, + final float red1, final float grn1, final float blu1, final float alpha, final float red2, final float grn2, final float blu2) { builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); if (xthick) @@ -806,11 +944,11 @@ public class ShapesRenderer } public static void drawBoxFaces( - Tesselator tessellator, BufferBuilder builder, - float x1, float y1, float z1, - float x2, float y2, float z2, - boolean xthick, boolean ythick, boolean zthick, - float red1, float grn1, float blu1, float alpha) + final Tesselator tessellator, final BufferBuilder builder, + final float x1, final float y1, final float z1, + final float x2, final float y2, final float z2, + final boolean xthick, final boolean ythick, final boolean zthick, + final float red1, final float grn1, final float blu1, final float alpha) { builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); @@ -866,14 +1004,14 @@ public class ShapesRenderer tessellator.end(); } - public static void drawCylinderWireframe(Tesselator tessellator, BufferBuilder builder, - float cx, float cy, float cz, - float r, float h, Direction.Axis axis, int subd, boolean isFlat, - float red, float grn, float blu, float alpha) + public static void drawCylinderWireframe(final Tesselator tessellator, final BufferBuilder builder, + final float cx, final float cy, final float cz, + final float r, final float h, final Direction.Axis axis, final int subd, final boolean isFlat, + final float red, final float grn, final float blu, final float alpha) { - float step = (float)Math.PI / (subd/2); - int num_steps180 = (int)(Math.PI / step)+1; - int num_steps360 = (int)(2*Math.PI / step); + final float step = (float) Math.PI / (subd / 2); + final int num_steps180 = (int) (Math.PI / step) + 1; + final int num_steps360 = (int) (2 * Math.PI / step); int hsteps = 1; float hstep = 1.0f; if (!isFlat) @@ -886,14 +1024,14 @@ public class ShapesRenderer { for (int dh = 0; dh < hsteps; dh++) { - float hh = dh*hstep; + final float hh = dh * hstep; builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip - for (int i = 0; i <= num_steps360+1; i++) + for (int i = 0; i <= num_steps360 + 1; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float y = hh; - float z = r * Mth.sin(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float y = hh; + final float z = r * Mth.sin(theta); builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); @@ -904,10 +1042,10 @@ public class ShapesRenderer for (int i = 0; i <= num_steps180; i++) { builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip - float theta = step * i; - float x = r * Mth.cos(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float z = r * Mth.sin(theta); builder.vertex(cx - x, cy + 0, cz + z).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + x, cy + 0, cz - z).color(red, grn, blu, alpha).endVertex(); @@ -922,9 +1060,9 @@ public class ShapesRenderer builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); for (int i = 0; i <= num_steps180; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); builder.vertex(cx - x, cy, cz + z).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + x, cy, cz - z).color(red, grn, blu, alpha).endVertex(); } @@ -936,14 +1074,14 @@ public class ShapesRenderer { for (int dh = 0; dh < hsteps; dh++) { - float hh = dh * hstep; + final float hh = dh * hstep; builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float z = r * Mth.cos(theta); - float x = hh; - float y = r * Mth.sin(theta); + final float theta = step * i; + final float z = r * Mth.cos(theta); + final float x = hh; + final float y = r * Mth.sin(theta); builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); @@ -954,10 +1092,10 @@ public class ShapesRenderer for (int i = 0; i <= num_steps180; i++) { builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip - float theta = step * i; - float y = r * Mth.cos(theta); + final float theta = step * i; + final float y = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float z = r * Mth.sin(theta); builder.vertex(cx + 0, cy - y, cz + z).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + 0, cy + y, cz - z).color(red, grn, blu, alpha).endVertex(); @@ -971,9 +1109,9 @@ public class ShapesRenderer builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); for (int i = 0; i <= num_steps180; i++) { - float theta = step * i; - float y = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float theta = step * i; + final float y = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); builder.vertex(cx, cy - y, cz + z).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx, cy + y, cz - z).color(red, grn, blu, alpha).endVertex(); } @@ -984,14 +1122,14 @@ public class ShapesRenderer { for (int dh = 0; dh < hsteps; dh++) { - float hh = dh * hstep; + final float hh = dh * hstep; builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float y = r * Mth.cos(theta); - float z = hh; - float x = r * Mth.sin(theta); + final float theta = step * i; + final float y = r * Mth.cos(theta); + final float z = hh; + final float x = r * Mth.sin(theta); builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); @@ -1001,10 +1139,10 @@ public class ShapesRenderer for (int i = 0; i <= num_steps180; i++) { builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip - float theta = step * i; - float x = r * Mth.cos(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); - float y = r * Mth.sin(theta); + final float y = r * Mth.sin(theta); builder.vertex(cx + x, cy - y, cz + 0).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx - x, cy + y, cz + 0).color(red, grn, blu, alpha).endVertex(); @@ -1018,9 +1156,9 @@ public class ShapesRenderer builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); for (int i = 0; i <= num_steps180; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float y = r * Mth.sin(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float y = r * Mth.sin(theta); builder.vertex(cx + x, cy - y, cz).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx - x, cy + y, cz).color(red, grn, blu, alpha).endVertex(); } @@ -1030,14 +1168,14 @@ public class ShapesRenderer } } - public static void drawCylinderFaces(Tesselator tessellator, BufferBuilder builder, - float cx, float cy, float cz, - float r, float h, Direction.Axis axis, int subd, boolean isFlat, - float red, float grn, float blu, float alpha) + public static void drawCylinderFaces(final Tesselator tessellator, final BufferBuilder builder, + final float cx, final float cy, final float cz, + final float r, final float h, final Direction.Axis axis, final int subd, final boolean isFlat, + final float red, final float grn, final float blu, final float alpha) { - float step = (float)Math.PI / (subd/2); - int num_steps180 = (int)(Math.PI / step)+1; - int num_steps360 = (int)(2*Math.PI / step)+1; + final float step = (float) Math.PI / (subd / 2); + //final int num_steps180 = (int) (Math.PI / step) + 1; + final int num_steps360 = (int) (2 * Math.PI / step) + 1; if (axis == Direction.Axis.Y) { @@ -1046,22 +1184,22 @@ public class ShapesRenderer builder.vertex(cx, cy, cz).color(red, grn, blu, alpha).endVertex(); for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); builder.vertex(x + cx, cy, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); if (!isFlat) { builder.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); - builder.vertex(cx, cy+h, cz).color(red, grn, blu, alpha).endVertex(); + builder.vertex(cx, cy + h, cz).color(red, grn, blu, alpha).endVertex(); for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float z = r * Mth.sin(theta); - builder.vertex(x + cx, cy+h, z + cz).color(red, grn, blu, alpha).endVertex(); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); + builder.vertex(x + cx, cy + h, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); @@ -1070,9 +1208,9 @@ public class ShapesRenderer float zp = r * 0; for (int i = 1; i <= num_steps360; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); builder.vertex(cx + xp, cy + 0, cz + zp).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + xp, cy + h, cz + zp).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + x, cy + h, cz + z).color(red, grn, blu, alpha).endVertex(); @@ -1090,22 +1228,22 @@ public class ShapesRenderer builder.vertex(cx, cy, cz).color(red, grn, blu, alpha).endVertex(); for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float y = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float theta = step * i; + final float y = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); builder.vertex(cx, cy + y, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); if (!isFlat) { builder.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); - builder.vertex(cx+h, cy, cz).color(red, grn, blu, alpha).endVertex(); + builder.vertex(cx + h, cy, cz).color(red, grn, blu, alpha).endVertex(); for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float y = r * Mth.cos(theta); - float z = r * Mth.sin(theta); - builder.vertex(cx+h, cy + y, cz + z).color(red, grn, blu, alpha).endVertex(); + final float theta = step * i; + final float y = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); + builder.vertex(cx + h, cy + y, cz + z).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); @@ -1114,9 +1252,9 @@ public class ShapesRenderer float zp = r * 0; for (int i = 1; i <= num_steps360; i++) { - float theta = step * i; - float y = r * Mth.cos(theta); - float z = r * Mth.sin(theta); + final float theta = step * i; + final float y = r * Mth.cos(theta); + final float z = r * Mth.sin(theta); builder.vertex(cx + 0, cy + yp, cz + zp).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + h, cy + yp, cz + zp).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + h, cy + y, cz + z).color(red, grn, blu, alpha).endVertex(); @@ -1133,22 +1271,22 @@ public class ShapesRenderer builder.vertex(cx, cy, cz).color(red, grn, blu, alpha).endVertex(); for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float y = r * Mth.sin(theta); - builder.vertex(x + cx, cy+y, cz).color(red, grn, blu, alpha).endVertex(); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float y = r * Mth.sin(theta); + builder.vertex(x + cx, cy + y, cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); if (!isFlat) { builder.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); - builder.vertex(cx, cy, cz+h).color(red, grn, blu, alpha).endVertex(); + builder.vertex(cx, cy, cz + h).color(red, grn, blu, alpha).endVertex(); for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float y = r * Mth.sin(theta); - builder.vertex(x + cx, cy+y, cz+h).color(red, grn, blu, alpha).endVertex(); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float y = r * Mth.sin(theta); + builder.vertex(x + cx, cy + y, cz + h).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); @@ -1157,9 +1295,9 @@ public class ShapesRenderer float yp = 0; for (int i = 1; i <= num_steps360; i++) { - float theta = step * i; - float x = r * Mth.cos(theta); - float y = r * Mth.sin(theta); + final float theta = step * i; + final float x = r * Mth.cos(theta); + final float y = r * Mth.sin(theta); builder.vertex(cx + xp, cy + yp, cz + 0).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + xp, cy + yp, cz + h).color(red, grn, blu, alpha).endVertex(); builder.vertex(cx + x, cy + y, cz + h).color(red, grn, blu, alpha).endVertex(); @@ -1172,59 +1310,59 @@ public class ShapesRenderer } } - public static void drawSphereWireframe(Tesselator tessellator, BufferBuilder builder, - float cx, float cy, float cz, - float r, int subd, - float red, float grn, float blu, float alpha) + public static void drawSphereWireframe(final Tesselator tessellator, final BufferBuilder builder, + final float cx, final float cy, final float cz, + final float r, final int subd, + final float red, final float grn, final float blu, final float alpha) { - float step = (float)Math.PI / (subd/2); - int num_steps180 = (int)(Math.PI / step)+1; - int num_steps360 = (int)(2*Math.PI / step)+1; + final float step = (float) Math.PI / (subd / 2); + final int num_steps180 = (int) (Math.PI / step) + 1; + final int num_steps360 = (int) (2 * Math.PI / step) + 1; for (int i = 0; i <= num_steps360; i++) { builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); - float theta = step * i ; + final float theta = step * i; for (int j = 0; j <= num_steps180; j++) { - float phi = step * j ; - float x = r * Mth.sin(phi) * Mth.cos(theta); - float z = r * Mth.sin(phi) * Mth.sin(theta); - float y = r * Mth.cos(phi); - builder.vertex(x+cx, y+cy, z+cz).color(red, grn, blu, alpha).endVertex(); + final float phi = step * j; + final float x = r * Mth.sin(phi) * Mth.cos(theta); + final float z = r * Mth.sin(phi) * Mth.sin(theta); + final float y = r * Mth.cos(phi); + builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); } for (int j = 0; j <= num_steps180; j++) { builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip - float phi = step * j ; + final float phi = step * j; for (int i = 0; i <= num_steps360; i++) { - float theta = step * i; - float x = r * Mth.sin(phi) * Mth.cos(theta); - float z = r * Mth.sin(phi) * Mth.sin(theta); - float y = r * Mth.cos(phi); - builder.vertex(x+cx, y+cy, z+cz).color(red, grn, blu, alpha).endVertex(); + final float theta = step * i; + final float x = r * Mth.sin(phi) * Mth.cos(theta); + final float z = r * Mth.sin(phi) * Mth.sin(theta); + final float y = r * Mth.cos(phi); + builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).endVertex(); } tessellator.end(); } } - public static void drawSphereFaces(Tesselator tessellator, BufferBuilder builder, - float cx, float cy, float cz, - float r, int subd, - float red, float grn, float blu, float alpha) + public static void drawSphereFaces(final Tesselator tessellator, final BufferBuilder builder, + final float cx, final float cy, final float cz, + final float r, final int subd, + final float red, final float grn, final float blu, final float alpha) { - float step = (float)Math.PI / (subd/2); - int num_steps180 = (int)(Math.PI / step)+1; - int num_steps360 = (int)(2*Math.PI / step); + final float step = (float) Math.PI / (subd / 2); + final int num_steps180 = (int) (Math.PI / step) + 1; + final int num_steps360 = (int) (2 * Math.PI / step); for (int i = 0; i <= num_steps360; i++) { - float theta = i * step; - float thetaprime = theta+step; + final float theta = i * step; + final float thetaprime = theta + step; builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads float xb = 0; float zb = 0; @@ -1233,12 +1371,12 @@ public class ShapesRenderer float yp = r; for (int j = 0; j <= num_steps180; j++) { - float phi = j * step; - float x = r * Mth.sin(phi) * Mth.cos(theta); - float z = r * Mth.sin(phi) * Mth.sin(theta); - float y = r * Mth.cos(phi); - float xp = r * Mth.sin(phi) * Mth.cos(thetaprime); - float zp = r * Mth.sin(phi) * Mth.sin(thetaprime); + final float phi = j * step; + final float x = r * Mth.sin(phi) * Mth.cos(theta); + final float z = r * Mth.sin(phi) * Mth.sin(theta); + final float y = r * Mth.cos(phi); + final float xp = r * Mth.sin(phi) * Mth.cos(thetaprime); + final float zp = r * Mth.sin(phi) * Mth.sin(thetaprime); builder.vertex(xb + cx, yp + cy, zb + cz).color(red, grn, blu, alpha).endVertex(); builder.vertex(xbp + cx, yp + cy, zbp + cz).color(red, grn, blu, alpha).endVertex(); builder.vertex(xp + cx, y + cy, zp + cz).color(red, grn, blu, alpha).endVertex(); diff --git a/src/main/java/carpet/script/utils/SimplexNoiseSampler.java b/src/main/java/carpet/script/utils/SimplexNoiseSampler.java index b9832c80..c56f955a 100644 --- a/src/main/java/carpet/script/utils/SimplexNoiseSampler.java +++ b/src/main/java/carpet/script/utils/SimplexNoiseSampler.java @@ -6,7 +6,8 @@ import java.util.Map; import java.util.Random; // extracted from import net.minecraft.util.math.noise.SimplexNoiseSampler -public class SimplexNoiseSampler extends PerlinNoiseSampler { +public class SimplexNoiseSampler extends PerlinNoiseSampler +{ private static final double sqrt3 = Math.sqrt(3.0D); private static final double SKEW_FACTOR_2D; private static final double UNSKEW_FACTOR_2D; @@ -14,23 +15,30 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler { public static SimplexNoiseSampler instance = new SimplexNoiseSampler(new Random(0)); public static Map samplers = new Long2ObjectOpenHashMap<>(); - public static SimplexNoiseSampler getSimplex(long aLong) + public static SimplexNoiseSampler getSimplex(final long aLong) { if (samplers.size() > 256) + { samplers.clear(); + } return samplers.computeIfAbsent(aLong, seed -> new SimplexNoiseSampler(new Random(seed))); } - public SimplexNoiseSampler(Random random) { + public SimplexNoiseSampler(final Random random) + { super(random); } - private double grad(int hash, double x, double y, double z, double d) { + private double grad(final int hash, final double x, final double y, final double z, final double d) + { double e = d - x * x - y * y - z * z; - double g; - if (e < 0.0D) { + final double g; + if (e < 0.0D) + { g = 0.0D; - } else { + } + else + { e *= e; g = e * e * PerlinNoiseSampler.dot3d(PerlinNoiseSampler.gradients3d[hash], x, y, z); } @@ -39,83 +47,94 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler { } @Override - public double sample2d(double x, double y) { - x = x/2; - y = y/2; - double d = (x + y) * SKEW_FACTOR_2D; - int i = PerlinNoiseSampler.floor(x + d); - int j = PerlinNoiseSampler.floor(y + d); - double e = (double)(i + j) * UNSKEW_FACTOR_2D; - double f = (double)i - e; - double g = (double)j - e; - double h = x - f; - double k = y - g; - byte n; - byte o; - if (h > k) { + public double sample2d(double x, double y) + { + x = x / 2; + y = y / 2; + final double d = (x + y) * SKEW_FACTOR_2D; + final int i = PerlinNoiseSampler.floor(x + d); + final int j = PerlinNoiseSampler.floor(y + d); + final double e = (i + j) * UNSKEW_FACTOR_2D; + final double f = i - e; + final double g = j - e; + final double h = x - f; + final double k = y - g; + final byte n; + final byte o; + if (h > k) + { n = 1; o = 0; - } else { + } + else + { n = 0; o = 1; } - double p = h - (double)n + UNSKEW_FACTOR_2D; - double q = k - (double)o + UNSKEW_FACTOR_2D; - double r = h - 1.0D + 2.0D * UNSKEW_FACTOR_2D; - double s = k - 1.0D + 2.0D * UNSKEW_FACTOR_2D; - int t = i & 255; - int u = j & 255; - int v = this.getGradient(t + this.getGradient(u)) % 12; - int w = this.getGradient(t + n + this.getGradient(u + o)) % 12; - int z = this.getGradient(t + 1 + this.getGradient(u + 1)) % 12; - double aa = this.grad(v, h, k, 0.0D, 0.5D); - double ab = this.grad(w, p, q, 0.0D, 0.5D); - double ac = this.grad(z, r, s, 0.0D, 0.5D); + final double p = h - n + UNSKEW_FACTOR_2D; + final double q = k - o + UNSKEW_FACTOR_2D; + final double r = h - 1.0D + 2.0D * UNSKEW_FACTOR_2D; + final double s = k - 1.0D + 2.0D * UNSKEW_FACTOR_2D; + final int t = i & 255; + final int u = j & 255; + final int v = this.getGradient(t + this.getGradient(u)) % 12; + final int w = this.getGradient(t + n + this.getGradient(u + o)) % 12; + final int z = this.getGradient(t + 1 + this.getGradient(u + 1)) % 12; + final double aa = this.grad(v, h, k, 0.0D, 0.5D); + final double ab = this.grad(w, p, q, 0.0D, 0.5D); + final double ac = this.grad(z, r, s, 0.0D, 0.5D); //return 70.0D * (aa + ab + ac); - return 35.0D * (aa + ab + ac)+0.5; + return 35.0D * (aa + ab + ac) + 0.5; } @Override - public double sample3d(double d, double e, double f) { - d = d/2; - e = e/2; - f = f/2; - double g = 0.3333333333333333D; - double h = (d + e + f) * 0.3333333333333333D; - int i = floor(d + h); - int j = floor(e + h); - int k = floor(f + h); - double l = 0.16666666666666666D; - double m = (double)(i + j + k) * 0.16666666666666666D; - double n = (double)i - m; - double o = (double)j - m; - double p = (double)k - m; - double q = d - n; - double r = e - o; - double s = f - p; - byte z; - byte aa; - byte ab; - byte ac; - byte ad; - byte bc; - if (q >= r) { - if (r >= s) { + public double sample3d(double d, double e, double f) + { + d = d / 2; + e = e / 2; + f = f / 2; + //final double g = 0.3333333333333333D; + final double h = (d + e + f) * 0.3333333333333333D; + final int i = floor(d + h); + final int j = floor(e + h); + final int k = floor(f + h); + //final double l = 0.16666666666666666D; + final double m = (i + j + k) * 0.16666666666666666D; + final double n = i - m; + final double o = j - m; + final double p = k - m; + final double q = d - n; + final double r = e - o; + final double s = f - p; + final byte z; + final byte aa; + final byte ab; + final byte ac; + final byte ad; + final byte bc; + if (q >= r) + { + if (r >= s) + { z = 1; aa = 0; ab = 0; ac = 1; ad = 1; bc = 0; - } else if (q >= s) { + } + else if (q >= s) + { z = 1; aa = 0; ab = 0; ac = 1; ad = 0; bc = 1; - } else { + } + else + { z = 0; aa = 0; ab = 1; @@ -123,21 +142,27 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler { ad = 0; bc = 1; } - } else if (r < s) { + } + else if (r < s) + { z = 0; aa = 0; ab = 1; ac = 0; ad = 1; bc = 1; - } else if (q < s) { + } + else if (q < s) + { z = 0; aa = 1; ab = 0; ac = 0; ad = 1; bc = 1; - } else { + } + else + { z = 0; aa = 1; ab = 0; @@ -146,30 +171,31 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler { bc = 0; } - double bd = q - (double)z + 0.16666666666666666D; - double be = r - (double)aa + 0.16666666666666666D; - double bf = s - (double)ab + 0.16666666666666666D; - double bg = q - (double)ac + 0.3333333333333333D; - double bh = r - (double)ad + 0.3333333333333333D; - double bi = s - (double)bc + 0.3333333333333333D; - double bj = q - 1.0D + 0.5D; - double bk = r - 1.0D + 0.5D; - double bl = s - 1.0D + 0.5D; - int bm = i & 255; - int bn = j & 255; - int bo = k & 255; - int bp = this.getGradient(bm + this.getGradient(bn + this.getGradient(bo))) % 12; - int bq = this.getGradient(bm + z + this.getGradient(bn + aa + this.getGradient(bo + ab))) % 12; - int br = this.getGradient(bm + ac + this.getGradient(bn + ad + this.getGradient(bo + bc))) % 12; - int bs = this.getGradient(bm + 1 + this.getGradient(bn + 1 + this.getGradient(bo + 1))) % 12; - double bt = this.grad(bp, q, r, s, 0.6D); - double bu = this.grad(bq, bd, be, bf, 0.6D); - double bv = this.grad(br, bg, bh, bi, 0.6D); - double bw = this.grad(bs, bj, bk, bl, 0.6D); + final double bd = q - z + 0.16666666666666666D; + final double be = r - aa + 0.16666666666666666D; + final double bf = s - ab + 0.16666666666666666D; + final double bg = q - ac + 0.3333333333333333D; + final double bh = r - ad + 0.3333333333333333D; + final double bi = s - bc + 0.3333333333333333D; + final double bj = q - 1.0D + 0.5D; + final double bk = r - 1.0D + 0.5D; + final double bl = s - 1.0D + 0.5D; + final int bm = i & 255; + final int bn = j & 255; + final int bo = k & 255; + final int bp = this.getGradient(bm + this.getGradient(bn + this.getGradient(bo))) % 12; + final int bq = this.getGradient(bm + z + this.getGradient(bn + aa + this.getGradient(bo + ab))) % 12; + final int br = this.getGradient(bm + ac + this.getGradient(bn + ad + this.getGradient(bo + bc))) % 12; + final int bs = this.getGradient(bm + 1 + this.getGradient(bn + 1 + this.getGradient(bo + 1))) % 12; + final double bt = this.grad(bp, q, r, s, 0.6D); + final double bu = this.grad(bq, bd, be, bf, 0.6D); + final double bv = this.grad(br, bg, bh, bi, 0.6D); + final double bw = this.grad(bs, bj, bk, bl, 0.6D); return 16.0D * (bt + bu + bv + bw) + 0.5; } - static { + static + { SKEW_FACTOR_2D = 0.5D * (sqrt3 - 1.0D); UNSKEW_FACTOR_2D = (3.0D - sqrt3) / 6.0D; } diff --git a/src/main/java/carpet/script/utils/SnoopyCommandSource.java b/src/main/java/carpet/script/utils/SnoopyCommandSource.java index 9e770984..03f5bec3 100644 --- a/src/main/java/carpet/script/utils/SnoopyCommandSource.java +++ b/src/main/java/carpet/script/utils/SnoopyCommandSource.java @@ -40,11 +40,12 @@ public class SnoopyCommandSource extends CommandSourceStack private final List chatOutput; private final CommandSigningContext signingContext; - public SnoopyCommandSource(CommandSourceStack original, Component[] error, List chatOutput) + public SnoopyCommandSource(final CommandSourceStack original, final Component[] error, final List chatOutput) { super(CommandSource.NULL, original.getPosition(), original.getRotation(), original.getLevel(), CarpetSettings.runPermissionLevel, original.getTextName(), original.getDisplayName(), original.getServer(), original.getEntity(), false, - (ctx, succ, res) -> { }, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer())); + (ctx, succ, res) -> { + }, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer())); this.output = CommandSource.NULL; this.position = original.getPosition(); this.world = original.getLevel(); @@ -53,7 +54,8 @@ public class SnoopyCommandSource extends CommandSourceStack this.name = original.getDisplayName(); this.server = original.getServer(); this.entity = original.getEntity(); - this.resultConsumer = (ctx, succ, res) -> { }; + this.resultConsumer = (ctx, succ, res) -> { + }; this.entityAnchor = original.getAnchor(); this.rotation = original.getRotation(); this.error = error; @@ -61,20 +63,22 @@ public class SnoopyCommandSource extends CommandSourceStack this.signingContext = original.getSigningContext(); } - public SnoopyCommandSource(ServerPlayer player, Component[] error, List output) { + public SnoopyCommandSource(final ServerPlayer player, final Component[] error, final List output) + { super(player, player.position(), player.getRotationVector(), - player.level instanceof ServerLevel ? (ServerLevel) player.level : null, + player.level instanceof final ServerLevel serverLevel ? serverLevel : null, player.server.getProfilePermissions(player.getGameProfile()), player.getName().getString(), player.getDisplayName(), player.level.getServer(), player); this.output = player; this.position = player.position(); - this.world = player.level instanceof ServerLevel ? (ServerLevel) player.level : null; + this.world = player.level instanceof final ServerLevel serverLevel ? serverLevel : null; this.level = player.server.getProfilePermissions(player.getGameProfile()); this.simpleName = player.getName().getString(); this.name = player.getDisplayName(); this.server = player.level.getServer(); this.entity = player; - this.resultConsumer = (ctx, succ, res) -> { }; + this.resultConsumer = (ctx, succ, res) -> { + }; this.entityAnchor = EntityAnchorArgument.Anchor.FEET; this.rotation = player.getRotationVector(); // not a client call really this.error = error; @@ -82,9 +86,10 @@ public class SnoopyCommandSource extends CommandSourceStack this.signingContext = CommandSigningContext.ANONYMOUS; } - private SnoopyCommandSource(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity, ResultConsumer consumer, EntityAnchorArgument.Anchor entityAnchor, CommandSigningContext context, - Component[] error, List chatOutput - ) { + private SnoopyCommandSource(final CommandSource output, final Vec3 pos, final Vec2 rot, final ServerLevel world, final int level, final String simpleName, final Component name, final MinecraftServer server, @Nullable final Entity entity, final ResultConsumer consumer, final EntityAnchorArgument.Anchor entityAnchor, final CommandSigningContext context, + final Component[] error, final List chatOutput + ) + { super(output, pos, rot, world, level, simpleName, name, server, entity, false, consumer, entityAnchor, context, TaskChainer.immediate(server)); @@ -105,33 +110,33 @@ public class SnoopyCommandSource extends CommandSourceStack } @Override - public CommandSourceStack withEntity(Entity entity) + public CommandSourceStack withEntity(final Entity entity) { return new SnoopyCommandSource(output, position, rotation, world, level, entity.getName().getString(), entity.getDisplayName(), server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput); } @Override - public CommandSourceStack withPosition(Vec3 position) + public CommandSourceStack withPosition(final Vec3 position) { return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput); } @Override - public CommandSourceStack withRotation(Vec2 rotation) + public CommandSourceStack withRotation(final Vec2 rotation) { return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput); } @Override - public CommandSourceStack withCallback(ResultConsumer consumer) + public CommandSourceStack withCallback(final ResultConsumer consumer) { return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, consumer, entityAnchor, signingContext, error, chatOutput); } @Override - public CommandSourceStack withCallback(ResultConsumer consumer, BinaryOperator> binaryOperator) + public CommandSourceStack withCallback(final ResultConsumer consumer, final BinaryOperator> binaryOperator) { - ResultConsumer resultConsumer = binaryOperator.apply(this.resultConsumer, consumer); + final ResultConsumer resultConsumer = binaryOperator.apply(this.resultConsumer, consumer); return this.withCallback(resultConsumer); } @@ -140,56 +145,58 @@ public class SnoopyCommandSource extends CommandSourceStack //public ServerCommandSource withSilent() { return this; } @Override - public CommandSourceStack withPermission(int level) + public CommandSourceStack withPermission(final int level) { return this; } @Override - public CommandSourceStack withMaximumPermission(int level) + public CommandSourceStack withMaximumPermission(final int level) { return this; } @Override - public CommandSourceStack withAnchor(EntityAnchorArgument.Anchor anchor) + public CommandSourceStack withAnchor(final EntityAnchorArgument.Anchor anchor) { return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, anchor, signingContext, error, chatOutput); } @Override - public CommandSourceStack withSigningContext(CommandSigningContext commandSigningContext) { + public CommandSourceStack withSigningContext(final CommandSigningContext commandSigningContext) + { return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, commandSigningContext, error, chatOutput); } @Override - public CommandSourceStack withLevel(ServerLevel world) + public CommandSourceStack withLevel(final ServerLevel world) { - double d = DimensionType.getTeleportationScale(this.world.dimensionType(), world.dimensionType()); - Vec3 position = new Vec3(this.position.x * d, this.position.y, this.position.z * d); + final double d = DimensionType.getTeleportationScale(this.world.dimensionType(), world.dimensionType()); + final Vec3 position = new Vec3(this.position.x * d, this.position.y, this.position.z * d); return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput); } @Override - public CommandSourceStack facing(Vec3 position) + public CommandSourceStack facing(final Vec3 position) { - Vec3 vec3d = this.entityAnchor.apply(this); - double d = position.x - vec3d.x; - double e = position.y - vec3d.y; - double f = position.z - vec3d.z; - double g = (double) Math.sqrt(d * d + f * f); - float h = Mth.wrapDegrees((float)(-(Mth.atan2(e, g) * 57.2957763671875D))); - float i = Mth.wrapDegrees((float)(Mth.atan2(f, d) * 57.2957763671875D) - 90.0F); + final Vec3 vec3d = this.entityAnchor.apply(this); + final double d = position.x - vec3d.x; + final double e = position.y - vec3d.y; + final double f = position.z - vec3d.z; + final double g = Math.sqrt(d * d + f * f); + final float h = Mth.wrapDegrees((float) (-(Mth.atan2(e, g) * 57.2957763671875D))); + final float i = Mth.wrapDegrees((float) (Mth.atan2(f, d) * 57.2957763671875D) - 90.0F); return this.withRotation(new Vec2(h, i)); } @Override - public void sendFailure(Component message) + public void sendFailure(final Component message) { error[0] = message; } + @Override - public void sendSuccess(Component message, boolean broadcastToOps) + public void sendSuccess(final Component message, final boolean broadcastToOps) { chatOutput.add(message); } diff --git a/src/main/java/carpet/script/utils/SystemInfo.java b/src/main/java/carpet/script/utils/SystemInfo.java index 02cb4ebc..dabf7240 100644 --- a/src/main/java/carpet/script/utils/SystemInfo.java +++ b/src/main/java/carpet/script/utils/SystemInfo.java @@ -25,6 +25,7 @@ import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.phys.Vec2; + import java.lang.management.ManagementFactory; import java.nio.file.Path; import java.util.ArrayList; @@ -36,15 +37,17 @@ import java.util.Map; import java.util.Objects; import java.util.function.Function; -public class SystemInfo { - private static final Map> options = new HashMap<>(){{ +public class SystemInfo +{ + private static final Map> options = new HashMap<>() + {{ put("app_name", c -> { - String name = c.host.getName(); - return name == null?Value.NULL:new StringValue(name); + final String name = c.host.getName(); + return name == null ? Value.NULL : new StringValue(name); }); - put("app_list", c -> ListValue.wrap(((CarpetScriptHost)c.host).scriptServer().modules.keySet().stream().filter(Objects::nonNull).map(StringValue::new))); - put("app_scope", c -> StringValue.of((c.host).isPerUser()?"player":"global")); + put("app_list", c -> ListValue.wrap(((CarpetScriptHost) c.host).scriptServer().modules.keySet().stream().filter(Objects::nonNull).map(StringValue::new))); + put("app_scope", c -> StringValue.of((c.host).isPerUser() ? "player" : "global")); put("app_players", c -> ListValue.wrap(c.host.getUserList().stream().map(StringValue::new))); put("world_name", c -> new StringValue(c.server().getWorldData().getLevelName())); @@ -52,30 +55,33 @@ public class SystemInfo { put("server_motd", c -> StringValue.of(c.server().getMotd())); put("world_path", c -> StringValue.of(c.server().getWorldPath(LevelResource.ROOT).toString())); put("world_folder", c -> { - Path serverPath = c.server().getWorldPath(LevelResource.ROOT); - int nodeCount = serverPath.getNameCount(); - if (nodeCount < 2) return Value.NULL; - String tlf = serverPath.getName(nodeCount-2).toString(); + final Path serverPath = c.server().getWorldPath(LevelResource.ROOT); + final int nodeCount = serverPath.getNameCount(); + if (nodeCount < 2) + { + return Value.NULL; + } + final String tlf = serverPath.getName(nodeCount - 2).toString(); return StringValue.of(tlf); }); put("world_dimensions", c -> ListValue.wrap(c.server().levelKeys().stream().map(k -> ValueConversions.of(k.location())))); put("world_spawn_point", c -> { - LevelData prop = c.server().overworld().getLevelData(); + final LevelData prop = c.server().overworld().getLevelData(); return ListValue.of(NumericValue.of(prop.getXSpawn()), NumericValue.of(prop.getYSpawn()), NumericValue.of(prop.getZSpawn())); }); - put("world_bottom", c-> new NumericValue(c.level().getMinBuildHeight())); + put("world_bottom", c -> new NumericValue(c.level().getMinBuildHeight())); - put("world_top", c-> new NumericValue(c.level().getMaxBuildHeight())); + put("world_top", c -> new NumericValue(c.level().getMaxBuildHeight())); - put("world_center", c-> { - WorldBorder worldBorder = c.level().getWorldBorder(); + put("world_center", c -> { + final WorldBorder worldBorder = c.level().getWorldBorder(); return ListValue.fromTriple(worldBorder.getCenterX(), 0, worldBorder.getCenterZ()); }); put("world_size", c -> new NumericValue(c.level().getWorldBorder().getSize() / 2)); - put("world_max_size", c-> new NumericValue( c.level().getWorldBorder().getAbsoluteMaxSize())); + put("world_max_size", c -> new NumericValue(c.level().getWorldBorder().getAbsoluteMaxSize())); put("world_time", c -> new NumericValue(c.level().getGameTime())); @@ -90,133 +96,137 @@ public class SystemInfo { put("game_target", c -> StringValue.of(CarpetSettings.releaseTarget)); put("game_protocol", c -> NumericValue.of(SharedConstants.getProtocolVersion())); put("game_major_target", c -> { - String [] vers = CarpetSettings.releaseTarget.split("\\."); - return NumericValue.of((vers.length > 1)?Integer.parseInt(vers[1]):0); + final String[] vers = CarpetSettings.releaseTarget.split("\\."); + return NumericValue.of((vers.length > 1) ? Integer.parseInt(vers[1]) : 0); }); put("game_minor_target", c -> { - String [] vers = CarpetSettings.releaseTarget.split("\\."); - return NumericValue.of((vers.length > 2)?Integer.parseInt(vers[2]):0); + final String[] vers = CarpetSettings.releaseTarget.split("\\."); + return NumericValue.of((vers.length > 2) ? Integer.parseInt(vers[2]) : 0); }); put("game_stable", c -> BooleanValue.of(SharedConstants.getCurrentVersion().isStable())); - put("game_data_version", c->NumericValue.of(SharedConstants.getCurrentVersion().getDataVersion().getVersion())); - put("game_pack_version", c->NumericValue.of(SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA))); + put("game_data_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().getDataVersion().getVersion())); + put("game_pack_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA))); put("server_ip", c -> StringValue.of(c.server().getLocalIp())); put("server_whitelisted", c -> BooleanValue.of(c.server().isEnforceWhitelist())); put("server_whitelist", c -> { - MapValue whitelist = new MapValue(Collections.emptyList()); - for (String s: c.server().getPlayerList().getWhiteListNames()) + final MapValue whitelist = new MapValue(Collections.emptyList()); + for (final String s : c.server().getPlayerList().getWhiteListNames()) { whitelist.append(StringValue.of(s)); } return whitelist; }); put("server_banned_players", c -> { - MapValue whitelist = new MapValue(Collections.emptyList()); - for (String s: c.server().getPlayerList().getBans().getUserList()) + final MapValue whitelist = new MapValue(Collections.emptyList()); + for (final String s : c.server().getPlayerList().getBans().getUserList()) { whitelist.append(StringValue.of(s)); } return whitelist; }); put("server_banned_ips", c -> { - MapValue whitelist = new MapValue(Collections.emptyList()); - for (String s: c.server().getPlayerList().getIpBans().getUserList()) + final MapValue whitelist = new MapValue(Collections.emptyList()); + for (final String s : c.server().getPlayerList().getIpBans().getUserList()) { whitelist.append(StringValue.of(s)); } return whitelist; }); - put("server_dev_environment", c-> BooleanValue.of(FabricLoader.getInstance().isDevelopmentEnvironment())); + put("server_dev_environment", c -> BooleanValue.of(FabricLoader.getInstance().isDevelopmentEnvironment())); put("server_mods", c -> { - Map ret = new HashMap<>(); - for (ModContainer mod : FabricLoader.getInstance().getAllMods()) + final Map ret = new HashMap<>(); + for (final ModContainer mod : FabricLoader.getInstance().getAllMods()) + { ret.put(new StringValue(mod.getMetadata().getId()), new StringValue(mod.getMetadata().getVersion().getFriendlyString())); + } return MapValue.wrap(ret); }); put("server_last_tick_times", c -> { - //assuming we are in the tick world section + //assuming we are in the tick world section // might be off one tick when run in the off tasks or asynchronously. - int currentReportedTick = c.server().getTickCount()-1; - List ticks = new ArrayList<>(100); + final int currentReportedTick = c.server().getTickCount() - 1; + final List ticks = new ArrayList<>(100); final long[] tickArray = c.server().tickTimes; - for (int i=currentReportedTick+100; i > currentReportedTick; i--) + for (int i = currentReportedTick + 100; i > currentReportedTick; i--) { - ticks.add(new NumericValue((tickArray[i % 100])/1000000.0)); + ticks.add(new NumericValue((tickArray[i % 100]) / 1000000.0)); } return ListValue.wrap(ticks); }); put("java_max_memory", c -> new NumericValue(Runtime.getRuntime().maxMemory())); put("java_allocated_memory", c -> new NumericValue(Runtime.getRuntime().totalMemory())); - put("java_used_memory", c -> new NumericValue(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())); + put("java_used_memory", c -> new NumericValue(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); put("java_cpu_count", c -> new NumericValue(Runtime.getRuntime().availableProcessors())); put("java_version", c -> StringValue.of(System.getProperty("java.version"))); put("java_bits", c -> { - for (String property : new String[]{"sun.arch.data.model", "com.ibm.vm.bitmode", "os.arch"}) + for (final String property : new String[]{"sun.arch.data.model", "com.ibm.vm.bitmode", "os.arch"}) { - String value = System.getProperty(property); + final String value = System.getProperty(property); if (value != null && value.contains("64")) + { return new NumericValue(64); - + } } return new NumericValue(32); }); put("java_system_cpu_load", c -> { - OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean( + final OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean( OperatingSystemMXBean.class); return new NumericValue(osBean.getCpuLoad()); }); put("java_process_cpu_load", c -> { - OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean( + final OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean( OperatingSystemMXBean.class); return new NumericValue(osBean.getProcessCpuLoad()); }); put("world_carpet_rules", c -> { - Collection> rules = CarpetServer.settingsManager.getCarpetRules(); - MapValue carpetRules = new MapValue(Collections.emptyList()); - rules.forEach(rule -> { - carpetRules.put(new StringValue(rule.name()), new StringValue(RuleHelper.toRuleString(rule.value()))); - }); + final Collection> rules = CarpetServer.settingsManager.getCarpetRules(); + final MapValue carpetRules = new MapValue(Collections.emptyList()); + rules.forEach(rule -> carpetRules.put(new StringValue(rule.name()), new StringValue(RuleHelper.toRuleString(rule.value())))); CarpetServer.extensions.forEach(e -> { - SettingsManager manager = e.extensionSettingsManager(); - if (manager == null) return; - - Collection> extensionRules = manager.getCarpetRules(); - extensionRules.forEach(rule -> { - carpetRules.put(new StringValue(manager.identifier()+":"+rule.name()), new StringValue(RuleHelper.toRuleString(rule.value()))); - }); + final SettingsManager manager = e.extensionSettingsManager(); + if (manager == null) + { + return; + } + manager.getCarpetRules().forEach(rule -> carpetRules.put(new StringValue(manager.identifier() + ":" + rule.name()), new StringValue(RuleHelper.toRuleString(rule.value())))); }); return carpetRules; }); - put("world_gamerules", c->{ - Map rules = new HashMap<>(); + put("world_gamerules", c -> { + final Map rules = new HashMap<>(); final GameRules gameRules = c.level().getGameRules(); - GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { + GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() + { @Override - public > void visit(GameRules.Key key, GameRules.Type type) { + public > void visit(final GameRules.Key key, final GameRules.Type type) + { rules.put(StringValue.of(key.getId()), StringValue.of(gameRules.getRule(key).toString())); } }); return MapValue.wrap(rules); }); - put("world_min_spawning_light", c-> NumericValue.of(c.level().dimensionType().monsterSpawnBlockLightLimit())); + put("world_min_spawning_light", c -> NumericValue.of(c.level().dimensionType().monsterSpawnBlockLightLimit())); put("source_entity", c -> EntityValue.of(c.source().getEntity())); put("source_position", c -> ValueConversions.of(c.source().getPosition())); put("source_dimension", c -> ValueConversions.of(c.level())); put("source_rotation", c -> { - Vec2 rotation = c.source().getRotation(); + final Vec2 rotation = c.source().getRotation(); return ListValue.of(new NumericValue(rotation.x), new NumericValue(rotation.y)); }); - + put("scarpet_version", c -> StringValue.of(CarpetSettings.carpetVersion)); }}; - public static Value get(String what, CarpetContext cc) + + public static Value get(final String what, final CarpetContext cc) { return options.getOrDefault(what, c -> null).apply(cc); } + public static Value getAll() { return ListValue.wrap(options.keySet().stream().map(StringValue::of)); diff --git a/src/main/java/carpet/script/utils/WorldTools.java b/src/main/java/carpet/script/utils/WorldTools.java index 1c9c0543..4235d43e 100644 --- a/src/main/java/carpet/script/utils/WorldTools.java +++ b/src/main/java/carpet/script/utils/WorldTools.java @@ -32,6 +32,7 @@ import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.storage.DerivedLevelData; import net.minecraft.world.level.storage.ServerLevelData; + import java.io.IOException; import java.nio.file.Path; import java.util.List; @@ -42,32 +43,48 @@ import java.util.Set; public class WorldTools { - public static boolean canHasChunk(ServerLevel world, ChunkPos chpos, Map regionCache, boolean deepcheck) + public static boolean canHasChunk(final ServerLevel world, final ChunkPos chpos, final Map regionCache, final boolean deepcheck) { if (world.getChunk(chpos.x, chpos.z, ChunkStatus.STRUCTURE_STARTS, false) != null) + { return true; - String currentRegionName = "r." + chpos.getRegionX() + "." + chpos.getRegionZ() + ".mca"; + } + final String currentRegionName = "r." + chpos.getRegionX() + "." + chpos.getRegionZ() + ".mca"; if (regionCache != null && regionCache.containsKey(currentRegionName)) { - RegionFile region = regionCache.get(currentRegionName); - if (region == null) return false; + final RegionFile region = regionCache.get(currentRegionName); + if (region == null) + { + return false; + } return region.hasChunk(chpos); } - Path regionsFolder = ((MinecraftServerInterface)world.getServer()).getCMSession().getDimensionPath(world.dimension()).resolve("region"); - Path regionPath = regionsFolder.resolve(currentRegionName); + final Path regionsFolder = ((MinecraftServerInterface) world.getServer()).getCMSession().getDimensionPath(world.dimension()).resolve("region"); + final Path regionPath = regionsFolder.resolve(currentRegionName); if (!regionPath.toFile().exists()) { - if (regionCache != null) regionCache.put(currentRegionName, null); + if (regionCache != null) + { + regionCache.put(currentRegionName, null); + } return false; } - if (!deepcheck) return true; // not using cache in this case. + if (!deepcheck) + { + return true; // not using cache in this case. + } try { - RegionFile region = new RegionFile(regionPath, regionsFolder, true); - if (regionCache != null) regionCache.put(currentRegionName, region); + final RegionFile region = new RegionFile(regionPath, regionsFolder, true); + if (regionCache != null) + { + regionCache.put(currentRegionName, region); + } return region.hasChunk(chpos); } - catch (IOException ignored) { } + catch (final IOException ignored) + { + } return true; } /* @@ -137,16 +154,16 @@ public class WorldTools return true; }*/ - public static void forceChunkUpdate(BlockPos pos, ServerLevel world) + public static void forceChunkUpdate(final BlockPos pos, final ServerLevel world) { - ChunkPos chunkPos = new ChunkPos(pos); - LevelChunk worldChunk = world.getChunkSource().getChunk(chunkPos.x, chunkPos.z, false); + final ChunkPos chunkPos = new ChunkPos(pos); + final LevelChunk worldChunk = world.getChunkSource().getChunk(chunkPos.x, chunkPos.z, false); if (worldChunk != null) { - List players = world.getChunkSource().chunkMap.getPlayers(chunkPos, false); + final List players = world.getChunkSource().chunkMap.getPlayers(chunkPos, false); if (!players.isEmpty()) { - ClientboundLevelChunkWithLightPacket packet = new ClientboundLevelChunkWithLightPacket(worldChunk, world.getLightEngine(), null, null, false); // false seems to update neighbours as well. + final ClientboundLevelChunkWithLightPacket packet = new ClientboundLevelChunkWithLightPacket(worldChunk, world.getLightEngine(), null, null, false); // false seems to update neighbours as well. players.forEach(p -> p.connection.send(packet)); } } @@ -155,11 +172,26 @@ public class WorldTools private static class NoopWorldGenerationProgressListener implements ChunkProgressListener { - @Override public void updateSpawnPos(ChunkPos spawnPos) { } - @Override public void onStatusChange(ChunkPos pos, ChunkStatus status) { } + @Override + public void updateSpawnPos(final ChunkPos spawnPos) + { + } + + @Override + public void onStatusChange(final ChunkPos pos, final ChunkStatus status) + { + } + @Environment(EnvType.CLIENT) - @Override public void start() { } - @Override public void stop() { } + @Override + public void start() + { + } + + @Override + public void stop() + { + } } public static final ChunkProgressListener NOOP_LISTENER = new NoopWorldGenerationProgressListener(); diff --git a/src/main/java/carpet/script/utils/shapes/ShapeDirection.java b/src/main/java/carpet/script/utils/shapes/ShapeDirection.java index 1836c3b9..9b7f3333 100644 --- a/src/main/java/carpet/script/utils/shapes/ShapeDirection.java +++ b/src/main/java/carpet/script/utils/shapes/ShapeDirection.java @@ -7,7 +7,8 @@ import net.minecraft.world.phys.Vec3; import java.util.Locale; -public enum ShapeDirection { +public enum ShapeDirection +{ NORTH, SOUTH, EAST, @@ -17,8 +18,10 @@ public enum ShapeDirection { CAMERA, PLAYER; - public static ShapeDirection fromString(String direction) { - return switch (direction.toLowerCase(Locale.ROOT)) { + public static ShapeDirection fromString(final String direction) + { + return switch (direction.toLowerCase(Locale.ROOT)) + { case "north" -> NORTH; case "south" -> SOUTH; case "east" -> EAST; @@ -31,8 +34,10 @@ public enum ShapeDirection { }; } - public static void rotatePoseStackByShapeDirection(PoseStack poseStack, ShapeDirection shapeDirection, Camera camera, Vec3 objectPos) { - switch (shapeDirection) { + public static void rotatePoseStackByShapeDirection(final PoseStack poseStack, final ShapeDirection shapeDirection, final Camera camera, final Vec3 objectPos) + { + switch (shapeDirection) + { case NORTH -> {} case SOUTH -> poseStack.mulPose(Axis.YP.rotationDegrees(180)); case EAST -> poseStack.mulPose(Axis.YP.rotationDegrees(270)); diff --git a/src/main/java/carpet/script/value/AbstractListValue.java b/src/main/java/carpet/script/value/AbstractListValue.java index 2bdf3f37..b8e60d08 100644 --- a/src/main/java/carpet/script/value/AbstractListValue.java +++ b/src/main/java/carpet/script/value/AbstractListValue.java @@ -8,21 +8,25 @@ import java.util.List; public abstract class AbstractListValue extends Value implements Iterable { - @Override public abstract Iterator iterator(); public List unpack() { - List retVal = Lists.newArrayList(iterator()); + final List retVal = Lists.newArrayList(iterator()); fatality(); return retVal; } - public void fatality() { } - public void append(Value v) + + public void fatality() + { + } + + public void append(final Value v) { throw new InternalExpressionException("Cannot append a value to an abstract list"); } @Override - public Value fromConstant() { + public Value fromConstant() + { return this.deepcopy(); } } diff --git a/src/main/java/carpet/script/value/BlockValue.java b/src/main/java/carpet/script/value/BlockValue.java index f42cee84..c4ec4df3 100644 --- a/src/main/java/carpet/script/value/BlockValue.java +++ b/src/main/java/carpet/script/value/BlockValue.java @@ -7,12 +7,14 @@ import carpet.script.exception.Throwables; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; + import net.minecraft.commands.arguments.blocks.BlockStateParser; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -44,42 +46,51 @@ public class BlockValue extends Value { private BlockState blockState; private final BlockPos pos; - @NotNull private final Level world; + @NotNull + private final Level world; private CompoundTag data; - public static BlockValue fromCoords(CarpetContext c, int x, int y, int z) + public static BlockValue fromCoords(final CarpetContext c, final int x, final int y, final int z) { - BlockPos pos = locateBlockPos(c, x,y,z); + final BlockPos pos = locateBlockPos(c, x, y, z); return new BlockValue(null, c.level(), pos); } - private static final Map bvCache= new HashMap<>(); - public static BlockValue fromString(String str, Level level) + private static final Map bvCache = new HashMap<>(); + + public static BlockValue fromString(final String str, final Level level) { try { BlockValue bv = bvCache.get(str); // [SCARY SHIT] persistent caches over server reloads - if (bv != null) return bv; - BlockStateParser.BlockResult foo = BlockStateParser.parseForBlock(level.registryAccess().lookupOrThrow(Registries.BLOCK), new StringReader(str), true ); + if (bv != null) + { + return bv; + } + final BlockStateParser.BlockResult foo = BlockStateParser.parseForBlock(level.registryAccess().lookupOrThrow(Registries.BLOCK), new StringReader(str), true); if (foo.blockState() != null) { CompoundTag bd = foo.nbt(); if (bd == null) + { bd = new CompoundTag(); - bv = new BlockValue(foo.blockState(), level, null, bd ); - if (bvCache.size()>10000) + } + bv = new BlockValue(foo.blockState(), level, null, bd); + if (bvCache.size() > 10000) + { bvCache.clear(); + } bvCache.put(str, bv); return bv; } } - catch (CommandSyntaxException ignored) + catch (final CommandSyntaxException ignored) { } throw new ThrowStatement(str, Throwables.UNKNOWN_BLOCK); } - public static BlockPos locateBlockPos(CarpetContext c, int xpos, int ypos, int zpos) + public static BlockPos locateBlockPos(final CarpetContext c, final int xpos, final int ypos, final int zpos) { final BlockPos pos = c.origin(); return new BlockPos(pos.getX() + xpos, pos.getY() + ypos, pos.getZ() + zpos); @@ -99,13 +110,13 @@ public class BlockValue extends Value throw new InternalExpressionException("Attempted to fetch block state without world or stored block state"); } - public static BlockEntity getBlockEntity(Level level, BlockPos pos) + public static BlockEntity getBlockEntity(final Level level, final BlockPos pos) { - if (level instanceof ServerLevel serverLevel) { - if (serverLevel.getServer().isSameThread()) - return serverLevel.getBlockEntity(pos); - else - return serverLevel.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE); + if (level instanceof final ServerLevel serverLevel) + { + return serverLevel.getServer().isSameThread() + ? serverLevel.getBlockEntity(pos) + : serverLevel.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE); } return null; } @@ -115,13 +126,11 @@ public class BlockValue extends Value { if (data != null) { - if (data.isEmpty()) - return null; - return data; + return data.isEmpty() ? null : data; } if (pos != null) { - BlockEntity be = getBlockEntity(world, pos); + final BlockEntity be = getBlockEntity(world, pos); if (be == null) { data = new CompoundTag(); @@ -134,7 +143,7 @@ public class BlockValue extends Value } - public BlockValue(BlockState state, @NotNull Level world, BlockPos position) + public BlockValue(final BlockState state, @NotNull final Level world, final BlockPos position) { this.world = world; blockState = state; @@ -142,7 +151,7 @@ public class BlockValue extends Value data = null; } - public BlockValue(BlockState state, @NotNull Level world, BlockPos position, CompoundTag nbt) + public BlockValue(final BlockState state, @NotNull final Level world, final BlockPos position, final CompoundTag nbt) { this.world = world; blockState = state; @@ -154,7 +163,7 @@ public class BlockValue extends Value @Override public String getString() { - Registry blockRegistry = world.registryAccess().registryOrThrow(Registries.BLOCK); + final Registry blockRegistry = world.registryAccess().registryOrThrow(Registries.BLOCK); return nameFromRegistryId(blockRegistry.getKey(getBlockState().getBlock())); } @@ -179,9 +188,9 @@ public class BlockValue extends Value @Override public int hashCode() { - if (pos != null ) - return GlobalPos.of(world.dimension() , pos).hashCode(); //getDimension().getType() - return ("b"+getString()).hashCode(); + return pos != null + ? GlobalPos.of(world.dimension(), pos).hashCode() + : ("b" + getString()).hashCode(); } public BlockPos getPos() @@ -189,29 +198,35 @@ public class BlockValue extends Value return pos; } - public Level getWorld() { return world;} + public Level getWorld() + { + return world; + } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } // follows falling block convertion - CompoundTag tag = new CompoundTag(); - CompoundTag state = new CompoundTag(); - BlockState s = getBlockState(); + final CompoundTag tag = new CompoundTag(); + final CompoundTag state = new CompoundTag(); + final BlockState s = getBlockState(); state.put("Name", StringTag.valueOf(world.registryAccess().registryOrThrow(Registries.BLOCK).getKey(s.getBlock()).toString())); - Collection> properties = s.getProperties(); + final Collection> properties = s.getProperties(); if (!properties.isEmpty()) { - CompoundTag props = new CompoundTag(); - for (Property p: properties) + final CompoundTag props = new CompoundTag(); + for (final Property p : properties) { props.put(p.getName(), StringTag.valueOf(s.getValue(p).toString().toLowerCase(Locale.ROOT))); } state.put("Properties", props); } tag.put("BlockState", state); - CompoundTag dataTag = getData(); + final CompoundTag dataTag = getData(); if (dataTag != null) { tag.put("TileEntityData", dataTag); @@ -219,29 +234,30 @@ public class BlockValue extends Value return tag; } - public enum SpecificDirection { - UP("up",0.5, 0.0, 0.5, Direction.UP), + public enum SpecificDirection + { + UP("up", 0.5, 0.0, 0.5, Direction.UP), - UPNORTH ("up-north", 0.5, 0.0, 0.4, Direction.UP), - UPSOUTH ("up-south", 0.5, 0.0, 0.6, Direction.UP), + UPNORTH("up-north", 0.5, 0.0, 0.4, Direction.UP), + UPSOUTH("up-south", 0.5, 0.0, 0.6, Direction.UP), UPEAST("up-east", 0.6, 0.0, 0.5, Direction.UP), UPWEST("up-west", 0.4, 0.0, 0.5, Direction.UP), DOWN("down", 0.5, 1.0, 0.5, Direction.DOWN), - DOWNNORTH ("down-north", 0.5, 1.0, 0.4, Direction.DOWN), - DOWNSOUTH ("down-south", 0.5, 1.0, 0.6, Direction.DOWN), + DOWNNORTH("down-north", 0.5, 1.0, 0.4, Direction.DOWN), + DOWNSOUTH("down-south", 0.5, 1.0, 0.6, Direction.DOWN), DOWNEAST("down-east", 0.6, 1.0, 0.5, Direction.DOWN), DOWNWEST("down-west", 0.4, 1.0, 0.5, Direction.DOWN), - NORTH ("north", 0.5, 0.4, 1.0, Direction.NORTH), - SOUTH ("south", 0.5, 0.4, 0.0, Direction.SOUTH), + NORTH("north", 0.5, 0.4, 1.0, Direction.NORTH), + SOUTH("south", 0.5, 0.4, 0.0, Direction.SOUTH), EAST("east", 0.0, 0.4, 0.5, Direction.EAST), WEST("west", 1.0, 0.4, 0.5, Direction.WEST), - NORTHUP ("north-up", 0.5, 0.6, 1.0, Direction.NORTH), - SOUTHUP ("south-up", 0.5, 0.6, 0.0, Direction.SOUTH), + NORTHUP("north-up", 0.5, 0.6, 1.0, Direction.NORTH), + SOUTHUP("south-up", 0.5, 0.6, 0.0, Direction.SOUTH), EASTUP("east-up", 0.0, 0.6, 0.5, Direction.EAST), WESTUP("west-up", 1.0, 0.6, 0.5, Direction.WEST); @@ -252,87 +268,94 @@ public class BlockValue extends Value private static final Map DIRECTION_MAP = Arrays.stream(values()).collect(Collectors.toMap(SpecificDirection::getName, d -> d)); - SpecificDirection(String name, double hitx, double hity, double hitz, Direction blockFacing) + SpecificDirection(final String name, final double hitx, final double hity, final double hitz, final Direction blockFacing) { this.name = name; this.hitOffset = new Vec3(hitx, hity, hitz); this.facing = blockFacing; } + private String getName() { return name; } } - public static class PlacementContext extends BlockPlaceContext { + public static class PlacementContext extends BlockPlaceContext + { private final Direction facing; private final boolean sneakPlace; - public static PlacementContext from(Level world, BlockPos pos, String direction, boolean sneakPlace, ItemStack itemStack) + public static PlacementContext from(final Level world, final BlockPos pos, final String direction, final boolean sneakPlace, final ItemStack itemStack) { - SpecificDirection dir = SpecificDirection.DIRECTION_MAP.get(direction); + final SpecificDirection dir = SpecificDirection.DIRECTION_MAP.get(direction); if (dir == null) - throw new InternalExpressionException("unknown block placement direction: "+direction); - BlockHitResult hitres = new BlockHitResult(Vec3.atLowerCornerOf(pos).add(dir.hitOffset), dir.facing, pos, false); + { + throw new InternalExpressionException("unknown block placement direction: " + direction); + } + final BlockHitResult hitres = new BlockHitResult(Vec3.atLowerCornerOf(pos).add(dir.hitOffset), dir.facing, pos, false); return new PlacementContext(world, dir.facing, sneakPlace, itemStack, hitres); } - private PlacementContext(Level world_1, Direction direction_1, boolean sneakPlace, ItemStack itemStack_1, BlockHitResult hitres) { + + private PlacementContext(final Level world_1, final Direction direction_1, final boolean sneakPlace, final ItemStack itemStack_1, final BlockHitResult hitres) + { super(world_1, null, InteractionHand.MAIN_HAND, itemStack_1, hitres); this.facing = direction_1; this.sneakPlace = sneakPlace; } @Override - public BlockPos getClickedPos() { - boolean prevcanReplaceExisting = replaceClicked; + public BlockPos getClickedPos() + { + final boolean prevcanReplaceExisting = replaceClicked; replaceClicked = true; - BlockPos ret = super.getClickedPos(); + final BlockPos ret = super.getClickedPos(); replaceClicked = prevcanReplaceExisting; return ret; } @Override - public Direction getNearestLookingDirection() { + public Direction getNearestLookingDirection() + { return facing.getOpposite(); } @Override - public Direction[] getNearestLookingDirections() { - switch(this.facing) { - case DOWN: - default: - return new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP}; - case UP: - return new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; - case NORTH: - return new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.SOUTH}; - case SOUTH: - return new Direction[]{Direction.DOWN, Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.NORTH}; - case WEST: - return new Direction[]{Direction.DOWN, Direction.WEST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.EAST}; - case EAST: - return new Direction[]{Direction.DOWN, Direction.EAST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.WEST}; - } + public Direction[] getNearestLookingDirections() + { + return switch (this.facing) + { + case DOWN -> new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP}; + case UP -> new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; + case NORTH -> new Direction[]{Direction.DOWN, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.SOUTH}; + case SOUTH -> new Direction[]{Direction.DOWN, Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.UP, Direction.NORTH}; + case WEST -> new Direction[]{Direction.DOWN, Direction.WEST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.EAST}; + case EAST -> new Direction[]{Direction.DOWN, Direction.EAST, Direction.SOUTH, Direction.UP, Direction.NORTH, Direction.WEST}; + }; } @Override - public Direction getHorizontalDirection() { + public Direction getHorizontalDirection() + { return this.facing.getAxis() == Direction.Axis.Y ? Direction.NORTH : this.facing; } @Override - public Direction getNearestLookingVerticalDirection() { + public Direction getNearestLookingVerticalDirection() + { return facing.getAxis() == Axis.Y ? facing : Direction.UP; } @Override - public boolean isSecondaryUseActive() { + public boolean isSecondaryUseActive() + { return sneakPlace; } @Override - public float getRotation() { - return (float)(this.facing.get2DDataValue() * 90); + public float getRotation() + { + return (float) (this.facing.get2DDataValue() * 90); } } } diff --git a/src/main/java/carpet/script/value/BooleanValue.java b/src/main/java/carpet/script/value/BooleanValue.java index 66c29bd0..d869590d 100644 --- a/src/main/java/carpet/script/value/BooleanValue.java +++ b/src/main/java/carpet/script/value/BooleanValue.java @@ -11,53 +11,63 @@ public class BooleanValue extends NumericValue public static final BooleanValue TRUE = new BooleanValue(true); boolean boolValue; - private BooleanValue(boolean boolval) { + + private BooleanValue(final boolean boolval) + { super(boolval ? 1L : 0L); boolValue = boolval; } - public static BooleanValue of(boolean value) + public static BooleanValue of(final boolean value) { return value ? TRUE : FALSE; } @Override - public String getString() { - return boolValue?"true":"false"; + public String getString() + { + return boolValue ? "true" : "false"; } @Override - public String getPrettyString() { + public String getPrettyString() + { return getString(); } @Override - public String getTypeString() { + public String getTypeString() + { return "bool"; } @Override - public Value clone() { + public Value clone() + { return new BooleanValue(boolValue); } @Override - public int hashCode() { + public int hashCode() + { return Boolean.hashCode(boolValue); } @Override - public Tag toTag(boolean force) { + public Tag toTag(final boolean force) + { return ByteTag.valueOf(boolValue); } @Override - public JsonElement toJson() { + public JsonElement toJson() + { return new JsonPrimitive(boolValue); } @Override - public boolean isInteger() { + public boolean isInteger() + { return true; } } diff --git a/src/main/java/carpet/script/value/ContainerValueInterface.java b/src/main/java/carpet/script/value/ContainerValueInterface.java index 6e05554a..55bbfc4e 100644 --- a/src/main/java/carpet/script/value/ContainerValueInterface.java +++ b/src/main/java/carpet/script/value/ContainerValueInterface.java @@ -3,11 +3,15 @@ package carpet.script.value; public interface ContainerValueInterface { boolean put(Value where, Value value); - default boolean put(Value where, Value value, Value conditions) + + default boolean put(final Value where, final Value value, final Value conditions) { return put(where, value); } + Value get(Value where); + boolean has(Value where); + boolean delete(Value where); } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 037a918d..4576f735 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -30,7 +30,6 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.StringTag; -import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket; import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket; import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; @@ -79,6 +78,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; + import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; @@ -103,19 +103,19 @@ public class EntityValue extends Value { private Entity entity; - public EntityValue(Entity e) + public EntityValue(final Entity e) { entity = e; } - public static Value of(Entity e) + public static Value of(final Entity e) { - if (e == null) return Value.NULL; - return new EntityValue(e); + return e == null ? Value.NULL : new EntityValue(e); } private static final Map selectorCache = new HashMap<>(); - public static Collection getEntitiesFromSelector(CommandSourceStack source, String selector) + + public static Collection getEntitiesFromSelector(final CommandSourceStack source, final String selector) { try { @@ -128,65 +128,50 @@ public class EntityValue extends Value selectorCache.put(selector, entitySelector); return entitySelector.findEntities(source.withMaximumPermission(4)); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { - throw new InternalExpressionException("Cannot select entities from "+selector); + throw new InternalExpressionException("Cannot select entities from " + selector); } } public Entity getEntity() { - if (entity instanceof ServerPlayer && ((ServerPlayerEntityInterface)entity).isInvalidEntityObject()) + if (entity instanceof ServerPlayer && ((ServerPlayerEntityInterface) entity).isInvalidEntityObject()) { - ServerPlayer newPlayer = entity.getServer().getPlayerList().getPlayer(entity.getUUID()); - if (newPlayer != null) entity = newPlayer; + final ServerPlayer newPlayer = entity.getServer().getPlayerList().getPlayer(entity.getUUID()); + if (newPlayer != null) + { + entity = newPlayer; + } } return entity; } - public static ServerPlayer getPlayerByValue(MinecraftServer server, Value value) + public static ServerPlayer getPlayerByValue(final MinecraftServer server, final Value value) { - ServerPlayer player = null; - if (value instanceof EntityValue) + if (value instanceof final EntityValue ev && ev.getEntity() instanceof final ServerPlayer sp) { - Entity e = ((EntityValue) value).getEntity(); - if (e instanceof ServerPlayer) - { - player = (ServerPlayer) e; - } + return sp; } - else if (value.isNull()) + if (value.isNull()) { return null; } - else - { - String playerName = value.getString(); - player = server.getPlayerList().getPlayerByName(playerName); - } - return player; + final String playerName = value.getString(); + return server.getPlayerList().getPlayerByName(playerName); } - public static String getPlayerNameByValue(Value value) + public static String getPlayerNameByValue(final Value value) { - String playerName = null; - if (value instanceof EntityValue) + if (value instanceof final EntityValue ev && ev.getEntity() instanceof final ServerPlayer sp) { - Entity e = ((EntityValue) value).getEntity(); - if (e instanceof ServerPlayer) - { - playerName = e.getScoreboardName(); - } + return sp.getScoreboardName(); } - else if (value.isNull()) + if (value.isNull()) { return null; } - else - { - playerName = value.getString(); - } - return playerName; + return value.getString(); } @Override @@ -202,22 +187,22 @@ public class EntityValue extends Value } @Override - public boolean equals(Object v) + public boolean equals(final Object v) { - if (v instanceof EntityValue) + if (v instanceof final EntityValue ev) { - return getEntity().getId()==((EntityValue) v).getEntity().getId(); + return getEntity().getId() == ev.getEntity().getId(); } - return super.equals((Value)v); + return super.equals(v); } @Override - public Value in(Value v) + public Value in(final Value v) { - if (v instanceof ListValue) + if (v instanceof final ListValue lv) { - List values = ((ListValue) v).getItems(); - String what = values.get(0).getString(); + final List values = lv.getItems(); + final String what = values.get(0).getString(); Value arg = null; if (values.size() == 2) { @@ -225,11 +210,11 @@ public class EntityValue extends Value } else if (values.size() > 2) { - arg = ListValue.wrap(values.subList(1,values.size())); + arg = ListValue.wrap(values.subList(1, values.size())); } return this.get(what, arg); } - String what = v.getString(); + final String what = v.getString(); return this.get(what, null); } @@ -247,9 +232,9 @@ public class EntityValue extends Value public static final EntityTypeTest ANY = EntityTypeTest.forClass(Entity.class); - public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server) + public static EntityClassDescriptor getEntityDescriptor(String who, final MinecraftServer server) { - EntityClassDescriptor eDesc = EntityClassDescriptor.byName.get(who); + final EntityClassDescriptor eDesc = EntityClassDescriptor.byName.get(who); if (eDesc == null) { boolean positive = true; @@ -258,16 +243,16 @@ public class EntityValue extends Value positive = false; who = who.substring(1); } - String booWho = who; - HolderSet.Named> eTagValue = server.registryAccess().registryOrThrow(Registries.ENTITY_TYPE) + final String booWho = who; + final HolderSet.Named> eTagValue = server.registryAccess().registryOrThrow(Registries.ENTITY_TYPE) .getTag(TagKey.create(Registries.ENTITY_TYPE, InputValidator.identifierOf(who))) - .orElseThrow( () -> new InternalExpressionException(booWho+" is not a valid entity descriptor")); - Set> eTag = eTagValue.stream().map(Holder::value).collect(Collectors.toUnmodifiableSet()); + .orElseThrow(() -> new InternalExpressionException(booWho + " is not a valid entity descriptor")); + final Set> eTag = eTagValue.stream().map(Holder::value).collect(Collectors.toUnmodifiableSet()); if (positive) { if (eTag.size() == 1) { - EntityType type = eTag.iterator().next(); + final EntityType type = eTag.iterator().next(); return new EntityClassDescriptor(type, Entity::isAlive, eTag.stream()); } else @@ -291,34 +276,36 @@ public class EntityValue extends Value public final Predicate filteringPredicate; public final List> types; - EntityClassDescriptor(EntityTypeTest type, Predicate predicate, List> types) + EntityClassDescriptor(final EntityTypeTest type, final Predicate predicate, final List> types) { this.directType = type; this.filteringPredicate = predicate; this.types = types; } - EntityClassDescriptor(EntityTypeTest type, Predicate predicate, Stream> types) + EntityClassDescriptor(final EntityTypeTest type, final Predicate predicate, final Stream> types) { this(type, predicate, types.toList()); } - public Value listValue(RegistryAccess regs) { + public Value listValue(final RegistryAccess regs) + { final Registry entityRegs = regs.registryOrThrow(Registries.ENTITY_TYPE); return ListValue.wrap(types.stream().map(et -> StringValue.of(nameFromRegistryId(entityRegs.getKey(et))))); } - public final static Map byName = new HashMap<>() {{ - List> allTypes = BuiltInRegistries.ENTITY_TYPE.stream().toList(); + public static final Map byName = new HashMap<>() + {{ + final List> allTypes = BuiltInRegistries.ENTITY_TYPE.stream().toList(); // nonliving types - Set> projectiles = Set.of( + final Set> projectiles = Set.of( EntityType.ARROW, EntityType.DRAGON_FIREBALL, EntityType.FIREWORK_ROCKET, EntityType.FIREBALL, EntityType.LLAMA_SPIT, EntityType.SMALL_FIREBALL, EntityType.SNOWBALL, EntityType.SPECTRAL_ARROW, EntityType.EGG, EntityType.ENDER_PEARL, EntityType.EXPERIENCE_BOTTLE, EntityType.POTION, EntityType.TRIDENT, EntityType.WITHER_SKULL, EntityType.FISHING_BOBBER, EntityType.SHULKER_BULLET ); - Set> deads = Set.of( + final Set> deads = Set.of( EntityType.AREA_EFFECT_CLOUD, EntityType.MARKER, EntityType.BOAT, EntityType.END_CRYSTAL, EntityType.EVOKER_FANGS, EntityType.EXPERIENCE_ORB, EntityType.EYE_OF_ENDER, EntityType.FALLING_BLOCK, EntityType.ITEM, EntityType.ITEM_FRAME, EntityType.GLOW_ITEM_FRAME, @@ -326,47 +313,47 @@ public class EntityValue extends Value EntityType.TNT, EntityType.ARMOR_STAND, EntityType.CHEST_BOAT ); - Set> minecarts = Set.of( - EntityType.MINECART, EntityType.CHEST_MINECART, EntityType.COMMAND_BLOCK_MINECART, + final Set> minecarts = Set.of( + EntityType.MINECART, EntityType.CHEST_MINECART, EntityType.COMMAND_BLOCK_MINECART, EntityType.FURNACE_MINECART, EntityType.HOPPER_MINECART, EntityType.SPAWNER_MINECART, EntityType.TNT_MINECART ); // living mob groups - non-defeault - Set> undeads = Set.of( + final Set> undeads = Set.of( EntityType.STRAY, EntityType.SKELETON, EntityType.WITHER_SKELETON, EntityType.ZOMBIE, EntityType.DROWNED, EntityType.ZOMBIE_VILLAGER, EntityType.ZOMBIE_HORSE, EntityType.SKELETON_HORSE, EntityType.PHANTOM, EntityType.WITHER, EntityType.ZOGLIN, EntityType.HUSK, EntityType.ZOMBIFIED_PIGLIN ); - Set> arthropods = Set.of( + final Set> arthropods = Set.of( EntityType.BEE, EntityType.ENDERMITE, EntityType.SILVERFISH, EntityType.SPIDER, EntityType.CAVE_SPIDER ); - Set> aquatique = Set.of( + final Set> aquatique = Set.of( EntityType.GUARDIAN, EntityType.TURTLE, EntityType.COD, EntityType.DOLPHIN, EntityType.PUFFERFISH, EntityType.SALMON, EntityType.SQUID, EntityType.TROPICAL_FISH ); - Set> illagers = Set.of( + final Set> illagers = Set.of( EntityType.PILLAGER, EntityType.ILLUSIONER, EntityType.VINDICATOR, EntityType.EVOKER, EntityType.RAVAGER, EntityType.WITCH ); - Set> living = allTypes.stream().filter(et -> + final Set> living = allTypes.stream().filter(et -> !deads.contains(et) && !projectiles.contains(et) && !minecarts.contains(et) ).collect(Collectors.toSet()); - Set> regular = allTypes.stream().filter(et -> + final Set> regular = allTypes.stream().filter(et -> living.contains(et) && !undeads.contains(et) && !arthropods.contains(et) && !aquatique.contains(et) && !illagers.contains(et) ).collect(Collectors.toSet()); - put("*", new EntityClassDescriptor(ANY, e -> true, allTypes) ); + put("*", new EntityClassDescriptor(ANY, e -> true, allTypes)); put("valid", new EntityClassDescriptor(ANY, net.minecraft.world.entity.EntitySelector.ENTITY_STILL_ALIVE, allTypes)); put("!valid", new EntityClassDescriptor(ANY, e -> !e.isAlive(), allTypes)); - put("living", new EntityClassDescriptor(EntityTypeTest.forClass(LivingEntity.class), net.minecraft.world.entity.EntitySelector.ENTITY_STILL_ALIVE, allTypes.stream().filter(living::contains))); - put("!living", new EntityClassDescriptor(ANY, (e) -> (!(e instanceof LivingEntity) && e.isAlive()), allTypes.stream().filter(et -> !living.contains(et)))); + put("living", new EntityClassDescriptor(EntityTypeTest.forClass(LivingEntity.class), net.minecraft.world.entity.EntitySelector.ENTITY_STILL_ALIVE, allTypes.stream().filter(living::contains))); + put("!living", new EntityClassDescriptor(ANY, (e) -> (!(e instanceof LivingEntity) && e.isAlive()), allTypes.stream().filter(et -> !living.contains(et)))); put("projectile", new EntityClassDescriptor(EntityTypeTest.forClass(Projectile.class), net.minecraft.world.entity.EntitySelector.ENTITY_STILL_ALIVE, allTypes.stream().filter(projectiles::contains))); put("!projectile", new EntityClassDescriptor(ANY, (e) -> (!(e instanceof Projectile) && e.isAlive()), allTypes.stream().filter(et -> !projectiles.contains(et) && !living.contains(et)))); @@ -392,49 +379,53 @@ public class EntityValue extends Value put("regular", new EntityClassDescriptor(EntityTypeTest.forClass(LivingEntity.class), e -> (((LivingEntity) e).getMobType() == MobType.UNDEFINED && e.isAlive()), allTypes.stream().filter(regular::contains))); put("!regular", new EntityClassDescriptor(EntityTypeTest.forClass(LivingEntity.class), e -> (((LivingEntity) e).getMobType() != MobType.UNDEFINED && e.isAlive()), allTypes.stream().filter(et -> !regular.contains(et) && living.contains(et)))); - for (ResourceLocation typeId : BuiltInRegistries.ENTITY_TYPE.keySet()) + for (final ResourceLocation typeId : BuiltInRegistries.ENTITY_TYPE.keySet()) { - EntityType type = BuiltInRegistries.ENTITY_TYPE.get(typeId); - String mobType = ValueConversions.simplify(typeId); - put( mobType, new EntityClassDescriptor(type, net.minecraft.world.entity.EntitySelector.ENTITY_STILL_ALIVE, Stream.of(type))); - put("!"+mobType, new EntityClassDescriptor(ANY, (e) -> e.getType() != type && e.isAlive(), allTypes.stream().filter(et -> et != type))); + final EntityType type = BuiltInRegistries.ENTITY_TYPE.get(typeId); + final String mobType = ValueConversions.simplify(typeId); + put(mobType, new EntityClassDescriptor(type, net.minecraft.world.entity.EntitySelector.ENTITY_STILL_ALIVE, Stream.of(type))); + put("!" + mobType, new EntityClassDescriptor(ANY, (e) -> e.getType() != type && e.isAlive(), allTypes.stream().filter(et -> et != type))); } - for (MobCategory catId : MobCategory.values()) + for (final MobCategory catId : MobCategory.values()) { - String catStr = catId.getName(); - put( catStr, new EntityClassDescriptor(ANY, e -> ((e.getType().getCategory() == catId) && e.isAlive()), allTypes.stream().filter(et -> et.getCategory() == catId))); - put("!"+catStr, new EntityClassDescriptor(ANY, e -> ((e.getType().getCategory() != catId) && e.isAlive()), allTypes.stream().filter(et -> et.getCategory() != catId))); + final String catStr = catId.getName(); + put(catStr, new EntityClassDescriptor(ANY, e -> ((e.getType().getCategory() == catId) && e.isAlive()), allTypes.stream().filter(et -> et.getCategory() == catId))); + put("!" + catStr, new EntityClassDescriptor(ANY, e -> ((e.getType().getCategory() != catId) && e.isAlive()), allTypes.stream().filter(et -> et.getCategory() != catId))); } }}; } - public Value get(String what, Value arg) + public Value get(final String what, final Value arg) { if (!(featureAccessors.containsKey(what))) - throw new InternalExpressionException("Unknown entity feature: "+what); + { + throw new InternalExpressionException("Unknown entity feature: " + what); + } try { return featureAccessors.get(what).apply(getEntity(), arg); } - catch (NullPointerException npe) + catch (final NullPointerException npe) { - throw new InternalExpressionException("Cannot fetch '"+what+"' with these arguments"); + throw new InternalExpressionException("Cannot fetch '" + what + "' with these arguments"); } } + private static final Map inventorySlots = Map.of( - "mainhand", EquipmentSlot.MAINHAND, - "offhand", EquipmentSlot.OFFHAND, - "head", EquipmentSlot.HEAD, - "chest", EquipmentSlot.CHEST, - "legs", EquipmentSlot.LEGS, - "feet", EquipmentSlot.FEET + "mainhand", EquipmentSlot.MAINHAND, + "offhand", EquipmentSlot.OFFHAND, + "head", EquipmentSlot.HEAD, + "chest", EquipmentSlot.CHEST, + "legs", EquipmentSlot.LEGS, + "feet", EquipmentSlot.FEET ); - private static final Map> featureAccessors = new HashMap>() {{ + private static final Map> featureAccessors = new HashMap>() + {{ //put("test", (e, a) -> a == null ? Value.NULL : new StringValue(a.getString())); put("removed", (entity, arg) -> BooleanValue.of(entity.isRemoved())); - put("uuid",(e, a) -> new StringValue(e.getStringUUID())); - put("id",(e, a) -> new NumericValue(e.getId())); + put("uuid", (e, a) -> new StringValue(e.getStringUUID())); + put("id", (e, a) -> new NumericValue(e.getId())); put("pos", (e, a) -> ListValue.of(new NumericValue(e.getX()), new NumericValue(e.getY()), new NumericValue(e.getZ()))); put("location", (e, a) -> ListValue.of(new NumericValue(e.getX()), new NumericValue(e.getY()), new NumericValue(e.getZ()), new NumericValue(e.getYRot()), new NumericValue(e.getXRot()))); put("x", (e, a) -> new NumericValue(e.getX())); @@ -442,7 +433,7 @@ public class EntityValue extends Value put("z", (e, a) -> new NumericValue(e.getZ())); put("motion", (e, a) -> { - Vec3 velocity = e.getDeltaMovement(); + final Vec3 velocity = e.getDeltaMovement(); return ListValue.of(new NumericValue(velocity.x), new NumericValue(velocity.y), new NumericValue(velocity.z)); }); put("motion_x", (e, a) -> new NumericValue(e.getDeltaMovement().x)); @@ -452,61 +443,52 @@ public class EntityValue extends Value put("name", (e, a) -> new StringValue(e.getName().getString())); put("display_name", (e, a) -> new FormattedTextValue(e.getDisplayName())); put("command_name", (e, a) -> new StringValue(e.getScoreboardName())); - put("custom_name", (e, a) -> e.hasCustomName()?new StringValue(e.getCustomName().getString()):Value.NULL); + put("custom_name", (e, a) -> e.hasCustomName() ? new StringValue(e.getCustomName().getString()) : Value.NULL); put("type", (e, a) -> new StringValue(nameFromRegistryId(e.getLevel().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getKey(e.getType())))); put("is_riding", (e, a) -> BooleanValue.of(e.isPassenger())); put("is_ridden", (e, a) -> BooleanValue.of(e.isVehicle())); put("passengers", (e, a) -> ListValue.wrap(e.getPassengers().stream().map(EntityValue::new))); - put("mount", (e, a) -> (e.getVehicle()!=null)?new EntityValue(e.getVehicle()):Value.NULL); - put("unmountable", (e, a) -> BooleanValue.of(((EntityInterface)e).isPermanentVehicle())); + put("mount", (e, a) -> (e.getVehicle() != null) ? new EntityValue(e.getVehicle()) : Value.NULL); + put("unmountable", (e, a) -> BooleanValue.of(((EntityInterface) e).isPermanentVehicle())); // deprecated put("tags", (e, a) -> ListValue.wrap(e.getTags().stream().map(StringValue::new))); put("scoreboard_tags", (e, a) -> ListValue.wrap(e.getTags().stream().map(StringValue::new))); put("entity_tags", (e, a) -> { - EntityType type = e.getType(); - return ListValue.wrap(e.getServer().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getTags().filter(entry -> entry.getSecond().stream().anyMatch(h -> h.value()==type)).map(entry -> ValueConversions.of(entry.getFirst()))); + final EntityType type = e.getType(); + return ListValue.wrap(e.getServer().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getTags().filter(entry -> entry.getSecond().stream().anyMatch(h -> h.value() == type)).map(entry -> ValueConversions.of(entry.getFirst()))); }); // deprecated put("has_tag", (e, a) -> BooleanValue.of(e.getTags().contains(a.getString()))); put("has_scoreboard_tag", (e, a) -> BooleanValue.of(e.getTags().contains(a.getString()))); put("has_entity_tag", (e, a) -> { - Optional>> tag = e.getServer().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getTag(TagKey.create(Registries.ENTITY_TYPE, InputValidator.identifierOf(a.getString()))); - if (tag.isEmpty()) return Value.NULL; + final Optional>> tag = e.getServer().registryAccess().registryOrThrow(Registries.ENTITY_TYPE).getTag(TagKey.create(Registries.ENTITY_TYPE, InputValidator.identifierOf(a.getString()))); + if (tag.isEmpty()) + { + return Value.NULL; + } //Tag> tag = e.getServer().getTags().getOrEmpty(Registry.ENTITY_TYPE_REGISTRY).getTag(InputValidator.identifierOf(a.getString())); //if (tag == null) return Value.NULL; //return BooleanValue.of(e.getType().is(tag)); - EntityType type = e.getType(); + final EntityType type = e.getType(); return BooleanValue.of(tag.get().stream().anyMatch(h -> h.value() == type)); }); - put("yaw", (e, a)-> new NumericValue(e.getYRot())); - put("head_yaw", (e, a)-> { - if (e instanceof LivingEntity) - { - return new NumericValue(e.getYHeadRot()); - } - return Value.NULL; - }); - put("body_yaw", (e, a)-> { - if (e instanceof LivingEntity) - { - return new NumericValue(((LivingEntity) e).yBodyRot); - } - return Value.NULL; - }); + put("yaw", (e, a) -> new NumericValue(e.getYRot())); + put("head_yaw", (e, a) -> e instanceof LivingEntity ? new NumericValue(e.getYHeadRot()) : Value.NULL); + put("body_yaw", (e, a) -> e instanceof final LivingEntity le ? new NumericValue(le.yBodyRot) : Value.NULL); - put("pitch", (e, a)-> new NumericValue(e.getXRot())); + put("pitch", (e, a) -> new NumericValue(e.getXRot())); put("look", (e, a) -> { - Vec3 look = e.getLookAngle(); - return ListValue.of(new NumericValue(look.x),new NumericValue(look.y),new NumericValue(look.z)); + final Vec3 look = e.getLookAngle(); + return ListValue.of(new NumericValue(look.x), new NumericValue(look.y), new NumericValue(look.z)); }); put("is_burning", (e, a) -> BooleanValue.of(e.isOnFire())); put("fire", (e, a) -> new NumericValue(e.getRemainingFireTicks())); put("is_freezing", (e, a) -> BooleanValue.of(e.isFullyFrozen())); put("frost", (e, a) -> new NumericValue(e.getTicksFrozen())); - put("silent", (e, a)-> BooleanValue.of(e.isSilent())); + put("silent", (e, a) -> BooleanValue.of(e.isSilent())); put("gravity", (e, a) -> BooleanValue.of(!e.isNoGravity())); put("immune_to_fire", (e, a) -> BooleanValue.of(e.fireImmune())); put("immune_to_frost", (e, a) -> BooleanValue.of(!e.canFreeze())); @@ -517,37 +499,21 @@ public class EntityValue extends Value put("width", (e, a) -> new NumericValue(e.getDimensions(Pose.STANDING).width)); put("eye_height", (e, a) -> new NumericValue(e.getEyeHeight())); put("age", (e, a) -> new NumericValue(e.tickCount)); - put("breeding_age", (e, a) -> e instanceof AgeableMob?new NumericValue(((AgeableMob) e).getAge()):Value.NULL); - put("despawn_timer", (e, a) -> e instanceof LivingEntity?new NumericValue(((LivingEntity) e).getNoActionTime()):Value.NULL); - put("blue_skull",(e,a)->{ - if (e instanceof WitherSkull w){ - return BooleanValue.of(w.isDangerous()); - } - return Value.NULL; - }); - put("offering_flower",(e,a)->{ - if (e instanceof IronGolem ig){ - return BooleanValue.of(ig.getOfferFlowerTick()>0); - } - return Value.NULL; - }); - put("item", (e, a) -> { - if(e instanceof ItemEntity) - return ValueConversions.of(((ItemEntity) e).getItem(), e.getServer().registryAccess()); - if(e instanceof ItemFrame) - return ValueConversions.of(((ItemFrame) e).getItem(), e.getServer().registryAccess()); - return Value.NULL; - }); - put("count", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntity) e).getItem().getCount()):Value.NULL); - put("pickup_delay", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntityInterface) e).getPickupDelayCM()):Value.NULL); - put("portal_cooldown", (e , a) ->new NumericValue(((EntityInterface)e).getPublicNetherPortalCooldown())); - put("portal_timer", (e , a) ->new NumericValue(((EntityInterface)e).getPortalTimer())); + put("breeding_age", (e, a) -> e instanceof final AgeableMob am ? new NumericValue(am.getAge()) : Value.NULL); + put("despawn_timer", (e, a) -> e instanceof final LivingEntity le ? new NumericValue(le.getNoActionTime()) : Value.NULL); + put("blue_skull", (e, a) -> e instanceof final WitherSkull w ? BooleanValue.of(w.isDangerous()) : Value.NULL); + put("offering_flower", (e, a) -> e instanceof final IronGolem ig ? BooleanValue.of(ig.getOfferFlowerTick() > 0) : Value.NULL); + put("item", (e, a) -> e instanceof final ItemEntity ie ? ValueConversions.of(ie.getItem(), e.getServer().registryAccess()) : e instanceof final ItemFrame frame ? ValueConversions.of(frame.getItem(), e.getServer().registryAccess()) : Value.NULL); + put("count", (e, a) -> (e instanceof final ItemEntity ie) ? new NumericValue(ie.getItem().getCount()) : Value.NULL); + put("pickup_delay", (e, a) -> (e instanceof ItemEntity) ? new NumericValue(((ItemEntityInterface) e).getPickupDelayCM()) : Value.NULL); + put("portal_cooldown", (e, a) -> new NumericValue(((EntityInterface) e).getPublicNetherPortalCooldown())); + put("portal_timer", (e, a) -> new NumericValue(((EntityInterface) e).getPortalTimer())); // ItemEntity -> despawn timer via ssGetAge - put("is_baby", (e, a) -> (e instanceof LivingEntity)?BooleanValue.of(((LivingEntity) e).isBaby()):Value.NULL); + put("is_baby", (e, a) -> (e instanceof final LivingEntity le) ? BooleanValue.of(le.isBaby()) : Value.NULL); put("target", (e, a) -> { - if (e instanceof Mob) + if (e instanceof final Mob mob) { - LivingEntity target = ((Mob) e).getTarget(); // there is also getAttacking in living.... + final LivingEntity target = mob.getTarget(); // there is also getAttacking in living.... if (target != null) { return new EntityValue(target); @@ -555,140 +521,85 @@ public class EntityValue extends Value } return Value.NULL; }); - put("home", (e, a) -> { - if (e instanceof Mob) - { - return (((Mob) e).getRestrictRadius () > 0)?new BlockValue(null, e.getCommandSenderWorld(), ((PathfinderMob) e).getRestrictCenter()):Value.FALSE; - } - return Value.NULL; - }); + put("home", (e, a) -> e instanceof final Mob mob ? (mob.getRestrictRadius() > 0) ? new BlockValue(null, e.getCommandSenderWorld(), mob.getRestrictCenter()) : Value.FALSE : Value.NULL); put("spawn_point", (e, a) -> { - if (e instanceof ServerPlayer spe) + if (e instanceof final ServerPlayer spe) { - if (spe.getRespawnPosition() == null) return Value.FALSE; + if (spe.getRespawnPosition() == null) + { + return Value.FALSE; + } return ListValue.of( ValueConversions.of(spe.getRespawnPosition()), ValueConversions.of(spe.getRespawnDimension()), new NumericValue(spe.getRespawnAngle()), BooleanValue.of(spe.isRespawnForced()) - ); + ); } return Value.NULL; }); put("pose", (e, a) -> new StringValue(e.getPose().name().toLowerCase(Locale.ROOT))); - put("sneaking", (e, a) -> e.isShiftKeyDown()?Value.TRUE:Value.FALSE); - put("sprinting", (e, a) -> e.isSprinting()?Value.TRUE:Value.FALSE); - put("swimming", (e, a) -> e.isSwimming()?Value.TRUE:Value.FALSE); - put("swinging", (e, a) -> { - if (e instanceof LivingEntity) return BooleanValue.of(((LivingEntity) e).swinging); - return Value.NULL; - }); - + put("sneaking", (e, a) -> e.isShiftKeyDown() ? Value.TRUE : Value.FALSE); + put("sprinting", (e, a) -> e.isSprinting() ? Value.TRUE : Value.FALSE); + put("swimming", (e, a) -> e.isSwimming() ? Value.TRUE : Value.FALSE); + put("swinging", (e, a) -> e instanceof final LivingEntity le ? BooleanValue.of(le.swinging) : Value.NULL); put("air", (e, a) -> new NumericValue(e.getAirSupply())); - put("language", (e, a)->{ - if(!(e instanceof ServerPlayer)) - return NULL; - String lang = ((ServerPlayerEntityInterface) e).getLanguage(); - return StringValue.of(lang); - }); - put("persistence", (e, a) -> { - if (e instanceof Mob) return BooleanValue.of(((Mob) e).isPersistenceRequired()); - return Value.NULL; - }); - put("hunger", (e, a) -> { - if(e instanceof Player) return new NumericValue(((Player) e).getFoodData().getFoodLevel()); - return Value.NULL; - }); - put("saturation", (e, a) -> { - if(e instanceof Player) return new NumericValue(((Player) e).getFoodData().getSaturationLevel()); - return Value.NULL; - }); - - put("exhaustion",(e, a)->{ - if(e instanceof Player) return new NumericValue(((Player) e).getFoodData().getExhaustionLevel()); - return Value.NULL; - }); - - put("absorption",(e, a)->{ - if(e instanceof Player) return new NumericValue(((Player) e).getAbsorptionAmount()); - return Value.NULL; - }); - - put("xp",(e, a)->{ - if(e instanceof Player) return new NumericValue(((Player) e).totalExperience); - return Value.NULL; - }); - - put("xp_level", (e, a)->{ - if(e instanceof Player) return new NumericValue(((Player) e).experienceLevel); - return Value.NULL; - }); - - put("xp_progress", (e, a)->{ - if(e instanceof Player) return new NumericValue(((Player) e).experienceProgress); - return Value.NULL; - }); - - put("score", (e, a)->{ - if(e instanceof Player) return new NumericValue(((Player) e).getScore()); - return Value.NULL; - }); - - put("jumping", (e, a) -> { - if (e instanceof LivingEntity) - { - return ((LivingEntityInterface) e).isJumpingCM()?Value.TRUE:Value.FALSE; - } - return Value.NULL; - }); - put("gamemode", (e, a) -> { - if (e instanceof ServerPlayer) - { - return new StringValue(((ServerPlayer) e).gameMode.getGameModeForPlayer().getName()); - } - return Value.NULL; - }); - + put("language", (e, a) -> !(e instanceof ServerPlayer) ? NULL : StringValue.of(((ServerPlayerEntityInterface) e).getLanguage())); + put("persistence", (e, a) -> e instanceof final Mob mob ? BooleanValue.of(mob.isPersistenceRequired()) : Value.NULL); + put("hunger", (e, a) -> e instanceof final Player player ? new NumericValue(player.getFoodData().getFoodLevel()) : Value.NULL); + put("saturation", (e, a) -> e instanceof final Player player ? new NumericValue(player.getFoodData().getSaturationLevel()) : Value.NULL); + put("exhaustion", (e, a) -> e instanceof final Player player ? new NumericValue(player.getFoodData().getExhaustionLevel()) : Value.NULL); + put("absorption", (e, a) -> e instanceof final Player player ? new NumericValue(player.getAbsorptionAmount()) : Value.NULL); + put("xp", (e, a) -> e instanceof final Player player ? new NumericValue(player.totalExperience) : Value.NULL); + put("xp_level", (e, a) -> e instanceof final Player player ? new NumericValue(player.experienceLevel) : Value.NULL); + put("xp_progress", (e, a) -> e instanceof final Player player ? new NumericValue(player.experienceProgress) : Value.NULL); + put("score", (e, a) -> e instanceof final Player player ? new NumericValue(player.getScore()) : Value.NULL); + put("jumping", (e, a) -> e instanceof LivingEntity ? ((LivingEntityInterface) e).isJumpingCM() ? Value.TRUE : Value.FALSE : Value.NULL); + put("gamemode", (e, a) -> e instanceof final ServerPlayer sp ? new StringValue(sp.gameMode.getGameModeForPlayer().getName()) : Value.NULL); put("path", (e, a) -> { - if (e instanceof Mob) + if (e instanceof final Mob mob) { - Path path = ((Mob)e).getNavigation().getPath(); - if (path == null) return Value.NULL; - return ValueConversions.fromPath((ServerLevel)e.getCommandSenderWorld(), path); + final Path path = mob.getNavigation().getPath(); + if (path == null) + { + return Value.NULL; + } + return ValueConversions.fromPath((ServerLevel) e.getCommandSenderWorld(), path); } return Value.NULL; }); put("brain", (e, a) -> { - String module = a.getString(); - MemoryModuleType moduleType = e.getLevel().registryAccess().registryOrThrow(Registries.MEMORY_MODULE_TYPE).get(InputValidator.identifierOf(module)); - if (moduleType == MemoryModuleType.DUMMY) return Value.NULL; - if (e instanceof LivingEntity livingEntity) + final String module = a.getString(); + final MemoryModuleType moduleType = e.getLevel().registryAccess().registryOrThrow(Registries.MEMORY_MODULE_TYPE).get(InputValidator.identifierOf(module)); + if (moduleType == MemoryModuleType.DUMMY) { - Brain brain = livingEntity.getBrain(); - Map, Optional>> memories = brain.getMemories(); - Optional> optmemory = memories.get(moduleType); - if (optmemory==null || !optmemory.isPresent()) return Value.NULL; - ExpirableValue memory = optmemory.get(); + return Value.NULL; + } + if (e instanceof final LivingEntity livingEntity) + { + final Brain brain = livingEntity.getBrain(); + final Map, Optional>> memories = brain.getMemories(); + final Optional> optmemory = memories.get(moduleType); + if (optmemory == null || !optmemory.isPresent()) + { + return Value.NULL; + } + final ExpirableValue memory = optmemory.get(); return ValueConversions.fromTimedMemory(e, memory.getTimeToLive(), memory.getValue()); } return Value.NULL; }); - put("gamemode_id", (e, a) -> { - if (e instanceof ServerPlayer) - { - return new NumericValue(((ServerPlayer) e).gameMode.getGameModeForPlayer().getId()); - } - return Value.NULL; - }); - + put("gamemode_id", (e, a) -> e instanceof final ServerPlayer sp ? new NumericValue(sp.gameMode.getGameModeForPlayer().getId()) : Value.NULL); put("permission_level", (e, a) -> { - if (e instanceof ServerPlayer spe) + if (e instanceof final ServerPlayer spe) { - for (int i=4; i>=0; i--) + for (int i = 4; i >= 0; i--) { if (spe.hasPermissions(i)) + { return new NumericValue(i); + } } return new NumericValue(0); @@ -697,161 +608,118 @@ public class EntityValue extends Value }); put("player_type", (e, a) -> { - if (e instanceof Player p) + if (e instanceof final Player p) { - if (e instanceof EntityPlayerMPFake) return new StringValue(((EntityPlayerMPFake) e).isAShadow?"shadow":"fake"); - MinecraftServer server = p.getCommandSenderWorld().getServer(); - if (server.isDedicatedServer()) return new StringValue("multiplayer"); - boolean runningLan = server.isPublished(); - if (!runningLan) return new StringValue("singleplayer"); - boolean isowner = server.isSingleplayerOwner(p.getGameProfile()); - if (isowner) return new StringValue("lan_host"); + if (e instanceof final EntityPlayerMPFake fake) + { + return new StringValue(fake.isAShadow ? "shadow" : "fake"); + } + final MinecraftServer server = p.getCommandSenderWorld().getServer(); + if (server.isDedicatedServer()) + { + return new StringValue("multiplayer"); + } + final boolean runningLan = server.isPublished(); + if (!runningLan) + { + return new StringValue("singleplayer"); + } + final boolean isowner = server.isSingleplayerOwner(p.getGameProfile()); + if (isowner) + { + return new StringValue("lan_host"); + } return new StringValue("lan player"); // realms? } return Value.NULL; }); - put("client_brand", (e, a) -> { - if (e instanceof ServerPlayer) - { - return StringValue.of(ServerNetworkHandler.getPlayerStatus((ServerPlayer) e)); - } - return Value.NULL; - }); - - put("team", (e, a) -> e.getTeam()==null?Value.NULL:new StringValue(e.getTeam().getName())); - - put("ping", (e, a) -> { - if (e instanceof ServerPlayer) - { - ServerPlayer spe = (ServerPlayer) e; - return new NumericValue(spe.latency); - } - return Value.NULL; - }); + put("client_brand", (e, a) -> e instanceof final ServerPlayer sp ? StringValue.of(ServerNetworkHandler.getPlayerStatus(sp)) : Value.NULL); + put("team", (e, a) -> e.getTeam() == null ? Value.NULL : new StringValue(e.getTeam().getName())); + put("ping", (e, a) -> e instanceof final ServerPlayer sp ? new NumericValue(sp.latency) : Value.NULL); //spectating_entity // isGlowing put("effect", (e, a) -> { - if (!(e instanceof LivingEntity)) + if (!(e instanceof final LivingEntity le)) { return Value.NULL; } if (a == null) { - List effects = new ArrayList<>(); - for (MobEffectInstance p : ((LivingEntity) e).getActiveEffects()) + final List effects = new ArrayList<>(); + for (final MobEffectInstance p : le.getActiveEffects()) { effects.add(ListValue.of( - new StringValue(p.getDescriptionId().replaceFirst("^effect\\.minecraft\\.", "")), - new NumericValue(p.getAmplifier()), - new NumericValue(p.getDuration()) + new StringValue(p.getDescriptionId().replaceFirst("^effect\\.minecraft\\.", "")), + new NumericValue(p.getAmplifier()), + new NumericValue(p.getDuration()) )); } return ListValue.wrap(effects); } - String effectName = a.getString(); - MobEffect potion = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)); + final String effectName = a.getString(); + final MobEffect potion = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)); if (potion == null) - throw new InternalExpressionException("No such an effect: "+effectName); - if (!((LivingEntity) e).hasEffect(potion)) - return Value.NULL; - MobEffectInstance pe = ((LivingEntity) e).getEffect(potion); - return ListValue.of( new NumericValue(pe.getAmplifier()), new NumericValue(pe.getDuration()) ); - }); - - put("health", (e, a) -> - { - if (e instanceof LivingEntity) { - return new NumericValue(((LivingEntity) e).getHealth()); + throw new InternalExpressionException("No such an effect: " + effectName); } - //if (e instanceof ItemEntity) - //{ - // e.h consider making item health public - //} - return Value.NULL; - }); - - put("may_fly", (e, a) -> { - if (e instanceof ServerPlayer player) { - return BooleanValue.of(player.getAbilities().mayfly); + if (!le.hasEffect(potion)) + { + return Value.NULL; } - return Value.NULL; - }); - - put("flying", (e, v) -> { - if (e instanceof ServerPlayer player) { - return BooleanValue.of(player.getAbilities().flying); - } - return Value.NULL; - }); - - put("may_build", (e, v) -> { - if (e instanceof ServerPlayer player) { - return BooleanValue.of(player.getAbilities().mayBuild); - } - return Value.NULL; - }); - - put("insta_build", (e, v) -> { - if (e instanceof ServerPlayer player) { - return BooleanValue.of(player.getAbilities().instabuild); - } - return Value.NULL; - }); - - put("fly_speed", (e, v) -> { - if (e instanceof ServerPlayer player) { - return NumericValue.of(player.getAbilities().getFlyingSpeed()); - } - return Value.NULL; - }); - - put("walk_speed", (e, v) -> { - if (e instanceof ServerPlayer player) { - return NumericValue.of(player.getAbilities().getWalkingSpeed()); - } - return Value.NULL; + final MobEffectInstance pe = le.getEffect(potion); + return ListValue.of(new NumericValue(pe.getAmplifier()), new NumericValue(pe.getDuration())); }); + put("health", (e, a) -> e instanceof final LivingEntity le ? new NumericValue(le.getHealth()) : Value.NULL); + put("may_fly", (e, a) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().mayfly) : Value.NULL); + put("flying", (e, v) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().flying) : Value.NULL); + put("may_build", (e, v) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().mayBuild) : Value.NULL); + put("insta_build", (e, v) -> e instanceof final ServerPlayer player ? BooleanValue.of(player.getAbilities().instabuild) : Value.NULL); + put("fly_speed", (e, v) -> e instanceof final ServerPlayer player ? NumericValue.of(player.getAbilities().getFlyingSpeed()) : Value.NULL); + put("walk_speed", (e, v) -> e instanceof final ServerPlayer player ? NumericValue.of(player.getAbilities().getWalkingSpeed()) : Value.NULL); put("holds", (e, a) -> { EquipmentSlot where = EquipmentSlot.MAINHAND; if (a != null) + { where = inventorySlots.get(a.getString()); + } if (where == null) - throw new InternalExpressionException("Unknown inventory slot: "+a.getString()); - if (e instanceof LivingEntity) - return ValueConversions.of(((LivingEntity)e).getItemBySlot(where), e.getServer().registryAccess()); + { + throw new InternalExpressionException("Unknown inventory slot: " + a.getString()); + } + if (e instanceof final LivingEntity le) + { + return ValueConversions.of(le.getItemBySlot(where), e.getServer().registryAccess()); + } return Value.NULL; }); - put("selected_slot", (e, a) -> { - if (e instanceof Player) - return new NumericValue(((Player) e).getInventory().selected); //getInventory - return Value.NULL; - }); + put("selected_slot", (e, a) -> e instanceof final Player p ? new NumericValue(p.getInventory().selected) : Value.NULL); put("active_block", (e, a) -> { - if (e instanceof ServerPlayer) + if (e instanceof final ServerPlayer sp) { - ServerPlayerInteractionManagerInterface manager = (ServerPlayerInteractionManagerInterface) (((ServerPlayer) e).gameMode); - BlockPos pos = manager.getCurrentBreakingBlock(); - if (pos == null) return Value.NULL; + final ServerPlayerInteractionManagerInterface manager = (ServerPlayerInteractionManagerInterface) (sp.gameMode); + final BlockPos pos = manager.getCurrentBreakingBlock(); + if (pos == null) + { + return Value.NULL; + } return new BlockValue(null, e.level, pos); } return Value.NULL; }); put("breaking_progress", (e, a) -> { - if (e instanceof ServerPlayer) + if (e instanceof final ServerPlayer sp) { - ServerPlayerInteractionManagerInterface manager = (ServerPlayerInteractionManagerInterface) (((ServerPlayer) e).gameMode); - int progress = manager.getCurrentBlockBreakingProgress(); - if (progress < 0) return Value.NULL; - return new NumericValue(progress); + final ServerPlayerInteractionManagerInterface manager = (ServerPlayerInteractionManagerInterface) (sp.gameMode); + final int progress = manager.getCurrentBlockBreakingProgress(); + return progress < 0 ? Value.NULL : new NumericValue(progress); } return Value.NULL; }); @@ -860,9 +728,13 @@ public class EntityValue extends Value put("facing", (e, a) -> { int index = 0; if (a != null) - index = (6+(int)NumericValue.asNumber(a).getLong())%6; + { + index = (6 + (int) NumericValue.asNumber(a).getLong()) % 6; + } if (index < 0 || index > 5) + { throw new InternalExpressionException("Facing order should be between -6 and 5"); + } return new StringValue(Direction.orderedByNearest(e)[index].getSerializedName()); }); @@ -875,17 +747,19 @@ public class EntityValue extends Value boolean blocks = true; boolean exact = false; - if (a!=null) + if (a != null) { - if (!(a instanceof ListValue)) + if (!(a instanceof final ListValue lv)) { reach = (float) NumericValue.asNumber(a).getDouble(); } else { - List args = ((ListValue) a).getItems(); - if (args.size()==0) + final List args = lv.getItems(); + if (args.size() == 0) + { throw new InternalExpressionException("'trace' needs more arguments"); + } reach = (float) NumericValue.asNumber(args.get(0)).getDouble(); if (args.size() > 1) { @@ -893,114 +767,153 @@ public class EntityValue extends Value blocks = false; for (int i = 1; i < args.size(); i++) { - String what = args.get(i).getString(); + final String what = args.get(i).getString(); if (what.equalsIgnoreCase("entities")) + { entities = true; + } else if (what.equalsIgnoreCase("blocks")) + { blocks = true; + } else if (what.equalsIgnoreCase("liquids")) + { liquids = true; + } else if (what.equalsIgnoreCase("exact")) + { exact = true; + } - else throw new InternalExpressionException("Incorrect tracing: "+what); + else + { + throw new InternalExpressionException("Incorrect tracing: " + what); + } } } } } - else if (e instanceof ServerPlayer && ((ServerPlayer) e).gameMode.isCreative()) + else if (e instanceof final ServerPlayer sp && sp.gameMode.isCreative()) { reach = 5.0f; } - HitResult hitres; + final HitResult hitres; if (entities && !blocks) - hitres = Tracer.rayTraceEntities(e, 1, reach, reach*reach); + { + hitres = Tracer.rayTraceEntities(e, 1, reach, reach * reach); + } else if (entities) + { hitres = Tracer.rayTrace(e, 1, reach, liquids); + } else + { hitres = Tracer.rayTraceBlocks(e, 1, reach, liquids); + } - if (hitres == null) return Value.NULL; - if (exact && hitres.getType() != HitResult.Type.MISS) return ValueConversions.of(hitres.getLocation()); + if (hitres == null) + { + return Value.NULL; + } + if (exact && hitres.getType() != HitResult.Type.MISS) + { + return ValueConversions.of(hitres.getLocation()); + } switch (hitres.getType()) { - case MISS: return Value.NULL; - case BLOCK: return new BlockValue(null, e.getCommandSenderWorld(), ((BlockHitResult)hitres).getBlockPos() ); - case ENTITY: return new EntityValue(((EntityHitResult)hitres).getEntity()); + case MISS: + return Value.NULL; + case BLOCK: + return new BlockValue(null, e.getCommandSenderWorld(), ((BlockHitResult) hitres).getBlockPos()); + case ENTITY: + return new EntityValue(((EntityHitResult) hitres).getEntity()); } return Value.NULL; }); - put("attribute", (e, a) ->{ - if (!(e instanceof LivingEntity)) return Value.NULL; - LivingEntity el = (LivingEntity)e; + put("attribute", (e, a) -> { + if (!(e instanceof final LivingEntity el)) + { + return Value.NULL; + } final Registry attributes = e.getLevel().registryAccess().registryOrThrow(Registries.ATTRIBUTE); if (a == null) { - AttributeMap container = el.getAttributes(); + final AttributeMap container = el.getAttributes(); return MapValue.wrap(attributes.stream().filter(container::hasAttribute).collect(Collectors.toMap(aa -> ValueConversions.of(attributes.getKey(aa)), aa -> NumericValue.of(container.getValue(aa))))); } - ResourceLocation id = InputValidator.identifierOf(a.getString()); - Attribute attrib = attributes.getOptional(id).orElseThrow( - () -> new InternalExpressionException("Unknown attribute: "+a.getString()) + final ResourceLocation id = InputValidator.identifierOf(a.getString()); + final Attribute attrib = attributes.getOptional(id).orElseThrow( + () -> new InternalExpressionException("Unknown attribute: " + a.getString()) ); - if (!el.getAttributes().hasAttribute(attrib)) return Value.NULL; + if (!el.getAttributes().hasAttribute(attrib)) + { + return Value.NULL; + } return NumericValue.of(el.getAttributeValue(attrib)); }); - put("nbt",(e, a) -> { - CompoundTag nbttagcompound = e.saveWithoutId((new CompoundTag())); - if (a==null) + put("nbt", (e, a) -> { + final CompoundTag nbttagcompound = e.saveWithoutId((new CompoundTag())); + if (a == null) + { return new NBTSerializableValue(nbttagcompound); + } return new NBTSerializableValue(nbttagcompound).get(a); }); - put("category",(e,a)->{return new StringValue(e.getType().getCategory().toString().toLowerCase(Locale.ROOT));}); + put("category", (e, a) -> { + return new StringValue(e.getType().getCategory().toString().toLowerCase(Locale.ROOT)); + }); }}; - public void set(String what, Value toWhat) + public void set(final String what, final Value toWhat) { if (!(featureModifiers.containsKey(what))) + { throw new InternalExpressionException("Unknown entity action: " + what); + } try { featureModifiers.get(what).accept(getEntity(), toWhat); } - catch (NullPointerException npe) + catch (final NullPointerException npe) { - throw new InternalExpressionException("'modify' for '"+what+"' expects a value"); + throw new InternalExpressionException("'modify' for '" + what + "' expects a value"); } - catch (IndexOutOfBoundsException ind) + catch (final IndexOutOfBoundsException ind) { - throw new InternalExpressionException("Wrong number of arguments for `modify` option: "+what); + throw new InternalExpressionException("Wrong number of arguments for `modify` option: " + what); } } - private static void updatePosition(Entity e, double x, double y, double z, float yaw, float pitch) + private static void updatePosition(final Entity e, final double x, final double y, final double z, final float yaw, final float pitch) { if ( !Double.isFinite(x) || Double.isNaN(x) || - !Double.isFinite(y) || Double.isNaN(y) || - !Double.isFinite(z) || Double.isNaN(z) || - !Float.isFinite(yaw) || Float.isNaN(yaw) || - !Float.isFinite(pitch) || Float.isNaN(pitch) + !Double.isFinite(y) || Double.isNaN(y) || + !Double.isFinite(z) || Double.isNaN(z) || + !Float.isFinite(yaw) || Float.isNaN(yaw) || + !Float.isFinite(pitch) || Float.isNaN(pitch) ) + { return; - if (e instanceof ServerPlayer) + } + if (e instanceof final ServerPlayer sp) { // this forces position but doesn't angles for some reason. Need both in the API in the future. - EnumSet set = EnumSet.noneOf(RelativeMovement.class); + final EnumSet set = EnumSet.noneOf(RelativeMovement.class); set.add(RelativeMovement.X_ROT); set.add(RelativeMovement.Y_ROT); - ((ServerPlayer)e).connection.teleport(x, y, z, yaw, pitch, set ); + sp.connection.teleport(x, y, z, yaw, pitch, set); } else { e.moveTo(x, y, z, yaw, pitch); // we were sending to players for not-living entites, that were untracked. Living entities should be tracked. //((ServerWorld) e.getEntityWorld()).getChunkManager().sendToNearbyPlayers(e, new EntityS2CPacket.(e)); - if (e instanceof LivingEntity le) + if (e instanceof final LivingEntity le) { le.yBodyRotO = le.yRotO = yaw; le.yHeadRotO = le.yHeadRot = yaw; @@ -1015,20 +928,22 @@ public class EntityValue extends Value } } - private static void updateVelocity(Entity e, double scale) + private static void updateVelocity(final Entity e, final double scale) { e.hurtMarked = true; if (Math.abs(scale) > 10000) - CarpetScriptServer.LOG.warn("Moved entity "+e.getScoreboardName()+" "+e.getName()+" at " +e.position()+" extremely fast: "+e.getDeltaMovement()); - //((ServerWorld)e.getEntityWorld()).method_14178().sendToNearbyPlayers(e, new EntityVelocityUpdateS2CPacket(e)); + { + CarpetScriptServer.LOG.warn("Moved entity " + e.getScoreboardName() + " " + e.getName() + " at " + e.position() + " extremely fast: " + e.getDeltaMovement()); + } } - private static final Map> featureModifiers = new HashMap>() {{ + private static final Map> featureModifiers = new HashMap>() + {{ put("remove", (entity, value) -> entity.discard()); // using discard here - will see other options if valid - put("age", (e, v) -> e.tickCount = Math.abs((int)NumericValue.asNumber(v).getLong()) ); + put("age", (e, v) -> e.tickCount = Math.abs((int) NumericValue.asNumber(v).getLong())); put("health", (e, v) -> { - float health = (float) NumericValue.asNumber(v).getDouble(); - if (health <= 0f && e instanceof ServerPlayer player) + final float health = (float) NumericValue.asNumber(v).getDouble(); + if (health <= 0f && e instanceof final ServerPlayer player) { if (player.containerMenu != null) { @@ -1039,14 +954,19 @@ public class EntityValue extends Value } ((LivingEntity) e).setHealth(health); } - if (e instanceof LivingEntity) ((LivingEntity) e).setHealth(health); + if (e instanceof final LivingEntity le) + { + le.setHealth(health); + } }); put("may_fly", (e, v) -> { - boolean mayFly = v.getBoolean(); - if (e instanceof ServerPlayer player) { + final boolean mayFly = v.getBoolean(); + if (e instanceof final ServerPlayer player) + { player.getAbilities().mayfly = mayFly; - if (!mayFly && player.getAbilities().flying) { + if (!mayFly && player.getAbilities().flying) + { player.getAbilities().flying = false; } player.onUpdateAbilities(); @@ -1054,40 +974,45 @@ public class EntityValue extends Value }); put("flying", (e, v) -> { - boolean flying = v.getBoolean(); - if (e instanceof ServerPlayer player) { + final boolean flying = v.getBoolean(); + if (e instanceof final ServerPlayer player) + { player.getAbilities().flying = flying; player.onUpdateAbilities(); } }); put("may_build", (e, v) -> { - boolean mayBuild = v.getBoolean(); - if (e instanceof ServerPlayer player) { + final boolean mayBuild = v.getBoolean(); + if (e instanceof final ServerPlayer player) + { player.getAbilities().mayBuild = mayBuild; player.onUpdateAbilities(); } }); put("insta_build", (e, v) -> { - boolean instaBuild = v.getBoolean(); - if (e instanceof ServerPlayer player) { + final boolean instaBuild = v.getBoolean(); + if (e instanceof final ServerPlayer player) + { player.getAbilities().instabuild = instaBuild; player.onUpdateAbilities(); } }); put("fly_speed", (e, v) -> { - float flySpeed = NumericValue.asNumber(v).getFloat(); - if (e instanceof ServerPlayer player) { + final float flySpeed = NumericValue.asNumber(v).getFloat(); + if (e instanceof final ServerPlayer player) + { player.getAbilities().setFlyingSpeed(flySpeed); player.onUpdateAbilities(); } }); put("walk_speed", (e, v) -> { - float walkSpeed = NumericValue.asNumber(v).getFloat(); - if (e instanceof ServerPlayer player) { + final float walkSpeed = NumericValue.asNumber(v).getFloat(); + if (e instanceof final ServerPlayer player) + { player.getAbilities().setWalkingSpeed(walkSpeed); player.onUpdateAbilities(); } @@ -1095,9 +1020,9 @@ public class EntityValue extends Value put("selected_slot", (e, v) -> { - if (e instanceof ServerPlayer player) + if (e instanceof final ServerPlayer player) { - int slot = NumericValue.asNumber(v).getInt(); + final int slot = NumericValue.asNumber(v).getInt(); player.connection.send(new ClientboundSetCarriedItemPacket(slot)); } }); @@ -1106,9 +1031,9 @@ public class EntityValue extends Value /*put("damage", (e, v) -> { float dmgPoints; DamageSource source; - if (v instanceof ListValue && ((ListValue) v).getItems().size() > 1) + if (v instanceof final ListValue lv && lv.getItems().size() > 1) { - List vals = ((ListValue) v).getItems(); + List vals = lv.getItems(); dmgPoints = (float) NumericValue.asNumber(v).getDouble(); source = DamageSource ... yeah... } @@ -1120,11 +1045,11 @@ public class EntityValue extends Value put("kill", (e, v) -> e.kill()); put("location", (e, v) -> { - if (!(v instanceof ListValue)) + if (!(v instanceof final ListValue lv)) { throw new InternalExpressionException("Expected a list of 5 parameters as a second argument"); } - List coords = ((ListValue) v).getItems(); + final List coords = lv.getItems(); updatePosition(e, NumericValue.asNumber(coords.get(0)).getDouble(), NumericValue.asNumber(coords.get(1)).getDouble(), @@ -1135,11 +1060,11 @@ public class EntityValue extends Value }); put("pos", (e, v) -> { - if (!(v instanceof ListValue)) + if (!(v instanceof final ListValue lv)) { throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); } - List coords = ((ListValue) v).getItems(); + final List coords = lv.getItems(); updatePosition(e, NumericValue.asNumber(coords.get(0)).getDouble(), NumericValue.asNumber(coords.get(1)).getDouble(), @@ -1148,55 +1073,46 @@ public class EntityValue extends Value e.getXRot() ); }); - put("x", (e, v) -> - { - updatePosition(e, NumericValue.asNumber(v).getDouble(), e.getY(), e.getZ(), e.getYRot(), e.getXRot()); - }); - put("y", (e, v) -> - { - updatePosition(e, e.getX(), NumericValue.asNumber(v).getDouble(), e.getZ(), e.getYRot(), e.getXRot()); - }); - put("z", (e, v) -> - { - updatePosition(e, e.getX(), e.getY(), NumericValue.asNumber(v).getDouble(), e.getYRot(), e.getXRot()); - }); - put("yaw", (e, v) -> - { - updatePosition(e, e.getX(), e.getY(), e.getZ(), ((float)NumericValue.asNumber(v).getDouble()) % 360, e.getXRot()); - }); + put("x", (e, v) -> updatePosition(e, NumericValue.asNumber(v).getDouble(), e.getY(), e.getZ(), e.getYRot(), e.getXRot())); + put("y", (e, v) -> updatePosition(e, e.getX(), NumericValue.asNumber(v).getDouble(), e.getZ(), e.getYRot(), e.getXRot())); + put("z", (e, v) -> updatePosition(e, e.getX(), e.getY(), NumericValue.asNumber(v).getDouble(), e.getYRot(), e.getXRot())); + put("yaw", (e, v) -> updatePosition(e, e.getX(), e.getY(), e.getZ(), ((float) NumericValue.asNumber(v).getDouble()) % 360, e.getXRot())); put("head_yaw", (e, v) -> { if (e instanceof LivingEntity) { - e.setYHeadRot((float)NumericValue.asNumber(v).getDouble() % 360); + e.setYHeadRot((float) NumericValue.asNumber(v).getDouble() % 360); } }); put("body_yaw", (e, v) -> { if (e instanceof LivingEntity) { - e.setYRot((float)NumericValue.asNumber(v).getDouble() % 360); + e.setYRot((float) NumericValue.asNumber(v).getDouble() % 360); } }); - put("pitch", (e, v) -> - { - updatePosition(e, e.getX(), e.getY(), e.getZ(), e.getYRot(), Mth.clamp((float)NumericValue.asNumber(v).getDouble(), -90, 90)); - }); + put("pitch", (e, v) -> updatePosition(e, e.getX(), e.getY(), e.getZ(), e.getYRot(), Mth.clamp((float) NumericValue.asNumber(v).getDouble(), -90, 90))); put("look", (e, v) -> { - if (!(v instanceof ListValue)) throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); - List vec = ((ListValue)v).getItems(); + if (!(v instanceof final ListValue lv)) + { + throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); + } + final List vec = lv.getItems(); float x = NumericValue.asNumber(vec.get(0)).getFloat(); float y = NumericValue.asNumber(vec.get(1)).getFloat(); float z = NumericValue.asNumber(vec.get(2)).getFloat(); - float l = Mth.sqrt(x*x + y*y + z*z); - if(l==0) return; + final float l = Mth.sqrt(x * x + y * y + z * z); + if (l == 0) + { + return; + } x /= l; y /= l; z /= l; - float pitch = (float) -Math.asin(y) / 0.017453292F; - float yaw = (float) (x==0 && z==0 ? e.getYRot() : Mth.atan2(-x,z) / 0.017453292F); + final float pitch = (float) -Math.asin(y) / 0.017453292F; + final float yaw = (float) (x == 0 && z == 0 ? e.getYRot() : Mth.atan2(-x, z) / 0.017453292F); updatePosition(e, e.getX(), e.getY(), e.getZ(), yaw, pitch); }); @@ -1205,11 +1121,11 @@ public class EntityValue extends Value put("move", (e, v) -> { - if (!(v instanceof ListValue)) + if (!(v instanceof final ListValue lv)) { throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); } - List coords = ((ListValue) v).getItems(); + final List coords = lv.getItems(); updatePosition(e, e.getX() + NumericValue.asNumber(coords.get(0)).getDouble(), e.getY() + NumericValue.asNumber(coords.get(1)).getDouble(), @@ -1221,46 +1137,46 @@ public class EntityValue extends Value put("motion", (e, v) -> { - if (!(v instanceof ListValue)) + if (!(v instanceof final ListValue lv)) { throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); } - List coords = ((ListValue) v).getItems(); - double dx = NumericValue.asNumber(coords.get(0)).getDouble(); - double dy = NumericValue.asNumber(coords.get(1)).getDouble(); - double dz = NumericValue.asNumber(coords.get(2)).getDouble(); + final List coords = lv.getItems(); + final double dx = NumericValue.asNumber(coords.get(0)).getDouble(); + final double dy = NumericValue.asNumber(coords.get(1)).getDouble(); + final double dz = NumericValue.asNumber(coords.get(2)).getDouble(); e.setDeltaMovement(dx, dy, dz); updateVelocity(e, Mth.absMax(Mth.absMax(dx, dy), dz)); }); put("motion_x", (e, v) -> { - Vec3 velocity = e.getDeltaMovement(); - double dv = NumericValue.asNumber(v).getDouble(); + final Vec3 velocity = e.getDeltaMovement(); + final double dv = NumericValue.asNumber(v).getDouble(); e.setDeltaMovement(dv, velocity.y, velocity.z); updateVelocity(e, dv); }); put("motion_y", (e, v) -> { - Vec3 velocity = e.getDeltaMovement(); - double dv = NumericValue.asNumber(v).getDouble(); + final Vec3 velocity = e.getDeltaMovement(); + final double dv = NumericValue.asNumber(v).getDouble(); e.setDeltaMovement(velocity.x, dv, velocity.z); updateVelocity(e, dv); }); put("motion_z", (e, v) -> { - Vec3 velocity = e.getDeltaMovement(); - double dv = NumericValue.asNumber(v).getDouble(); + final Vec3 velocity = e.getDeltaMovement(); + final double dv = NumericValue.asNumber(v).getDouble(); e.setDeltaMovement(velocity.x, velocity.y, dv); updateVelocity(e, dv); }); put("accelerate", (e, v) -> { - if (!(v instanceof ListValue)) + if (!(v instanceof final ListValue lv)) { throw new InternalExpressionException("Expected a list of 3 parameters as a second argument"); } - List coords = ((ListValue) v).getItems(); + final List coords = lv.getItems(); e.push( NumericValue.asNumber(coords.get(0)).getDouble(), NumericValue.asNumber(coords.get(1)).getDouble(), @@ -1277,10 +1193,10 @@ public class EntityValue extends Value return; } boolean showName = false; - if (v instanceof ListValue) + if (v instanceof final ListValue lv) { - showName = ((ListValue) v).getItems().get(1).getBoolean(); - v = ((ListValue) v).getItems().get(0); + showName = lv.getItems().get(1).getBoolean(); + v = lv.getItems().get(0); } e.setCustomNameVisible(showName); e.setCustomName(FormattedTextValue.getTextByValue(v)); @@ -1288,54 +1204,83 @@ public class EntityValue extends Value put("persistence", (e, v) -> { - if (!(e instanceof Mob)) return; - if (v == null) v = Value.TRUE; - ((MobEntityInterface)e).setPersistence(v.getBoolean()); + if (!(e instanceof Mob)) + { + return; + } + if (v == null) + { + v = Value.TRUE; + } + ((MobEntityInterface) e).setPersistence(v.getBoolean()); }); - put("dismount", (e, v) -> e.stopRiding() ); + put("dismount", (e, v) -> e.stopRiding()); put("mount", (e, v) -> { - if (v instanceof EntityValue) + if (v instanceof final EntityValue ev) { - e.startRiding(((EntityValue) v).getEntity(),true); + e.startRiding(ev.getEntity(), true); } - if (e instanceof ServerPlayer) + if (e instanceof final ServerPlayer sp) { - ((ServerPlayer)e).connection.send(new ClientboundSetPassengersPacket(e)); - //... + sp.connection.send(new ClientboundSetPassengersPacket(e)); } }); - put("unmountable", (e, v) ->{ - if (v == null) - v = Value.TRUE; - ((EntityInterface)e).setPermanentVehicle(v.getBoolean()); - }); + put("unmountable", (e, v) -> ((EntityInterface) e).setPermanentVehicle(v == null || v.getBoolean())); put("drop_passengers", (e, v) -> e.ejectPassengers()); put("mount_passengers", (e, v) -> { - if (v==null) + if (v == null) + { throw new InternalExpressionException("'mount_passengers' needs entities to ride"); - if (v instanceof EntityValue) - ((EntityValue) v).getEntity().startRiding(e); - else if (v instanceof ListValue) - for (Value element : ((ListValue) v).getItems()) - if (element instanceof EntityValue) - ((EntityValue) element).getEntity().startRiding(e); + } + if (v instanceof final EntityValue ev) + { + ev.getEntity().startRiding(e); + } + else if (v instanceof final ListValue lv) + { + for (final Value element : lv.getItems()) + { + if (element instanceof final EntityValue ev) + { + ev.getEntity().startRiding(e); + } + } + } }); put("tag", (e, v) -> { - if (v==null) + if (v == null) + { throw new InternalExpressionException("'tag' requires parameters"); - if (v instanceof ListValue) - for (Value element : ((ListValue) v).getItems()) e.addTag(element.getString()); + } + if (v instanceof final ListValue lv) + { + for (final Value element : lv.getItems()) + { + e.addTag(element.getString()); + } + } else + { e.addTag(v.getString()); + } }); put("clear_tag", (e, v) -> { - if (v==null) + if (v == null) + { throw new InternalExpressionException("'clear_tag' requires parameters"); - if (v instanceof ListValue) - for (Value element : ((ListValue) v).getItems()) e.removeTag(element.getString()); + } + if (v instanceof final ListValue lv) + { + for (final Value element : lv.getItems()) + { + e.removeTag(element.getString()); + } + } else + { e.removeTag(v.getString()); + } }); //put("target", (e, v) -> { // // attacks indefinitely - might need to do it through tasks @@ -1347,96 +1292,110 @@ public class EntityValue extends Value //}); put("breeding_age", (e, v) -> { - if (e instanceof AgeableMob) + if (e instanceof final AgeableMob am) { - ((AgeableMob) e).setAge((int)NumericValue.asNumber(v).getLong()); + am.setAge((int) NumericValue.asNumber(v).getLong()); } }); put("talk", (e, v) -> { // attacks indefinitely - if (e instanceof Mob) + if (e instanceof final Mob mob) { - ((Mob) e).playAmbientSound(); + mob.playAmbientSound(); } }); put("home", (e, v) -> { - if (!(e instanceof PathfinderMob)) + if (!(e instanceof final PathfinderMob ec)) + { return; - PathfinderMob ec = (PathfinderMob)e; + } if (v == null) + { throw new InternalExpressionException("'home' requires at least one position argument, and optional distance, or null to cancel"); + } if (v.isNull()) { ec.restrictTo(BlockPos.ZERO, -1); - Map tasks = ((MobEntityInterface)ec).getTemporaryTasks(); - ((MobEntityInterface)ec).getAI(false).removeGoal(tasks.get("home")); + final Map tasks = ((MobEntityInterface) ec).getTemporaryTasks(); + ((MobEntityInterface) ec).getAI(false).removeGoal(tasks.get("home")); tasks.remove("home"); return; } - BlockPos pos; + final BlockPos pos; int distance = 16; - if (v instanceof BlockValue) + if (v instanceof final BlockValue bv) { - pos = ((BlockValue) v).getPos(); - if (pos == null) throw new InternalExpressionException("Block is not positioned in the world"); - } - else if (v instanceof ListValue) - { - List lv = ((ListValue) v).getItems(); - Vector3Argument locator = Vector3Argument.findIn(lv, 0, false, false); - pos = new BlockPos(locator.vec.x, locator.vec.y, locator.vec.z); - if (lv.size() > locator.offset) + pos = bv.getPos(); + if (pos == null) { - distance = (int) NumericValue.asNumber(lv.get(locator.offset)).getLong(); + throw new InternalExpressionException("Block is not positioned in the world"); } } - else throw new InternalExpressionException("'home' requires at least one position argument, and optional distance"); + else if (v instanceof final ListValue lv) + { + final List list = lv.getItems(); + final Vector3Argument locator = Vector3Argument.findIn(list, 0, false, false); + pos = new BlockPos(locator.vec.x, locator.vec.y, locator.vec.z); + if (list.size() > locator.offset) + { + distance = (int) NumericValue.asNumber(list.get(locator.offset)).getLong(); + } + } + else + { + throw new InternalExpressionException("'home' requires at least one position argument, and optional distance"); + } ec.restrictTo(pos, distance); - Map tasks = ((MobEntityInterface)ec).getTemporaryTasks(); + final Map tasks = ((MobEntityInterface) ec).getTemporaryTasks(); if (!tasks.containsKey("home")) { - Goal task = new MoveTowardsRestrictionGoal(ec, 1.0D); + final Goal task = new MoveTowardsRestrictionGoal(ec, 1.0D); tasks.put("home", task); - ((MobEntityInterface)ec).getAI(false).addGoal(10, task); + ((MobEntityInterface) ec).getAI(false).addGoal(10, task); } }); //requires mixing put("spawn_point", (e, a) -> { - if (!(e instanceof ServerPlayer spe)) return; + if (!(e instanceof final ServerPlayer spe)) + { + return; + } if (a == null) { spe.setRespawnPosition(null, null, 0, false, false); } - else if (a instanceof ListValue) + else if (a instanceof final ListValue lv) { - List params= ((ListValue) a).getItems(); - Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false, false); - BlockPos pos = new BlockPos(blockLocator.vec); + final List params = lv.getItems(); + final Vector3Argument blockLocator = Vector3Argument.findIn(params, 0, false, false); + final BlockPos pos = new BlockPos(blockLocator.vec); ResourceKey world = spe.getCommandSenderWorld().dimension(); float angle = spe.getYHeadRot(); boolean forced = false; if (params.size() > blockLocator.offset) { - Value worldValue = params.get(blockLocator.offset+0); + final Value worldValue = params.get(blockLocator.offset + 0); world = ValueConversions.dimFromValue(worldValue, spe.getServer()).dimension(); - if (params.size() > blockLocator.offset+1) + if (params.size() > blockLocator.offset + 1) { - angle = NumericValue.asNumber(params.get(blockLocator.offset+1), "angle").getFloat(); - if (params.size() > blockLocator.offset+2) + angle = NumericValue.asNumber(params.get(blockLocator.offset + 1), "angle").getFloat(); + if (params.size() > blockLocator.offset + 2) { - forced = params.get(blockLocator.offset+2).getBoolean(); + forced = params.get(blockLocator.offset + 2).getBoolean(); } } } spe.setRespawnPosition(world, pos, angle, forced, false); } - else if (a instanceof BlockValue bv) + else if (a instanceof final BlockValue bv) { - if (bv.getPos()==null || bv.getWorld() == null) + if (bv.getPos() == null || bv.getWorld() == null) + { throw new InternalExpressionException("block for spawn modification should be localised in the world"); + } spe.setRespawnPosition(bv.getWorld().dimension(), bv.getPos(), e.getYRot(), true, false); // yaw } else if (a.isNull()) @@ -1446,128 +1405,159 @@ public class EntityValue extends Value else { throw new InternalExpressionException("modifying player respawn point requires a block position, optional world, optional angle, and optional force"); - } }); put("pickup_delay", (e, v) -> { - if (e instanceof ItemEntity) + if (e instanceof final ItemEntity ie) { - ((ItemEntity) e).setPickUpDelay((int)NumericValue.asNumber(v).getLong()); + ie.setPickUpDelay((int) NumericValue.asNumber(v).getLong()); } }); put("despawn_timer", (e, v) -> { - if (e instanceof LivingEntity) + if (e instanceof final LivingEntity le) { - ((LivingEntity) e).setNoActionTime((int)NumericValue.asNumber(v).getLong()); + le.setNoActionTime((int) NumericValue.asNumber(v).getLong()); } }); - put("portal_cooldown", (e , v) -> + put("portal_cooldown", (e, v) -> { - if (v==null) + if (v == null) + { throw new InternalExpressionException("'portal_cooldown' requires a value to set"); - ((EntityInterface)e).setPublicNetherPortalCooldown(NumericValue.asNumber(v).getInt()); + } + ((EntityInterface) e).setPublicNetherPortalCooldown(NumericValue.asNumber(v).getInt()); }); - put("portal_timer", (e , v) -> + put("portal_timer", (e, v) -> { - if (v==null) + if (v == null) + { throw new InternalExpressionException("'portal_timer' requires a value to set"); + } ((EntityInterface) e).setPortalTimer(NumericValue.asNumber(v).getInt()); }); put("ai", (e, v) -> { - if (e instanceof Mob) + if (e instanceof final Mob mob) { - ((Mob) e).setNoAi(!v.getBoolean()); + mob.setNoAi(!v.getBoolean()); } }); put("no_clip", (e, v) -> { if (v == null) + { e.noPhysics = true; + } else + { e.noPhysics = v.getBoolean(); + } }); put("effect", (e, v) -> { - if (!(e instanceof LivingEntity le)) return; + if (!(e instanceof final LivingEntity le)) + { + return; + } if (v == null) { le.removeAllEffects(); return; } - else if (v instanceof ListValue) + else if (v instanceof final ListValue lv) { - List lv = ((ListValue) v).getItems(); - if (lv.size() >= 1 && lv.size() <= 6) + final List list = lv.getItems(); + if (list.size() >= 1 && list.size() <= 6) { - String effectName = lv.get(0).getString(); - MobEffect effect = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)); + final String effectName = list.get(0).getString(); + final MobEffect effect = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)); if (effect == null) - throw new InternalExpressionException("Wrong effect name: "+effectName); - if (lv.size() == 1) + { + throw new InternalExpressionException("Wrong effect name: " + effectName); + } + if (list.size() == 1) { le.removeEffect(effect); return; } - int duration = (int)NumericValue.asNumber(lv.get(1)).getLong(); + final int duration = (int) NumericValue.asNumber(list.get(1)).getLong(); if (duration <= 0) { le.removeEffect(effect); return; } int amplifier = 0; - if (lv.size() > 2) - amplifier = (int)NumericValue.asNumber(lv.get(2)).getLong(); + if (list.size() > 2) + { + amplifier = (int) NumericValue.asNumber(list.get(2)).getLong(); + } boolean showParticles = true; - if (lv.size() > 3) - showParticles = lv.get(3).getBoolean(); + if (list.size() > 3) + { + showParticles = list.get(3).getBoolean(); + } boolean showIcon = true; - if (lv.size() > 4) - showIcon = lv.get(4).getBoolean(); + if (list.size() > 4) + { + showIcon = list.get(4).getBoolean(); + } boolean ambient = false; - if (lv.size() > 5) - ambient = lv.get(5).getBoolean(); + if (list.size() > 5) + { + ambient = list.get(5).getBoolean(); + } le.addEffect(new MobEffectInstance(effect, duration, amplifier, ambient, showParticles, showIcon)); return; } } else { - String effectName = v.getString(); - MobEffect effect = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)); + final String effectName = v.getString(); + final MobEffect effect = BuiltInRegistries.MOB_EFFECT.get(InputValidator.identifierOf(effectName)); if (effect == null) - throw new InternalExpressionException("Wrong effect name: "+effectName); + { + throw new InternalExpressionException("Wrong effect name: " + effectName); + } le.removeEffect(effect); return; } throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles, show icon and ambient"); }); - put("gamemode", (e,v)->{ - if(!(e instanceof ServerPlayer)) return; - GameType toSet = v instanceof NumericValue ? - GameType.byId(((NumericValue) v).getInt()) : + put("gamemode", (e, v) -> { + if (!(e instanceof final ServerPlayer sp)) + { + return; + } + final GameType toSet = v instanceof final NumericValue number ? + GameType.byId(number.getInt()) : GameType.byName(v.getString().toLowerCase(Locale.ROOT), null); - if (toSet != null) ((ServerPlayer) e).setGameMode(toSet); + if (toSet != null) + { + sp.setGameMode(toSet); + } }); - put("jumping",(e,v)->{ - if(!(e instanceof LivingEntity)) return; - ((LivingEntity) e).setJumping(v.getBoolean()); + put("jumping", (e, v) -> { + if (!(e instanceof final LivingEntity le)) + { + return; + } + le.setJumping(v.getBoolean()); }); - put("jump",(e,v)->{ + put("jump", (e, v) -> { if (e instanceof LivingEntity) { - ((LivingEntityInterface)e).doJumpCM(); + ((LivingEntityInterface) e).doJumpCM(); } else { @@ -1576,83 +1566,112 @@ public class EntityValue extends Value }); put("swing", (e, v) -> { - if (e instanceof LivingEntity) + if (e instanceof final LivingEntity le) { InteractionHand hand = InteractionHand.MAIN_HAND; if (v != null) { - String handString = v.getString().toLowerCase(Locale.ROOT); - if (handString.equals("offhand") || handString.equals("off_hand")) hand = InteractionHand.OFF_HAND; + final String handString = v.getString().toLowerCase(Locale.ROOT); + if (handString.equals("offhand") || handString.equals("off_hand")) + { + hand = InteractionHand.OFF_HAND; + } } - ((LivingEntity)e).swing(hand, true); + le.swing(hand, true); } }); - put("silent",(e,v)-> e.setSilent(v.getBoolean())); + put("silent", (e, v) -> e.setSilent(v.getBoolean())); - put("gravity",(e,v)-> e.setNoGravity(!v.getBoolean())); + put("gravity", (e, v) -> e.setNoGravity(!v.getBoolean())); - put("invulnerable",(e,v)-> { - boolean invulnerable = v.getBoolean(); - if (e instanceof ServerPlayer player) { + put("invulnerable", (e, v) -> { + final boolean invulnerable = v.getBoolean(); + if (e instanceof final ServerPlayer player) + { player.getAbilities().invulnerable = invulnerable; player.onUpdateAbilities(); - } else { + } + else + { e.setInvulnerable(invulnerable); } }); - put("fire",(e,v)-> e.setRemainingFireTicks((int)NumericValue.asNumber(v).getLong())); - put("frost",(e,v)-> e.setTicksFrozen((int)NumericValue.asNumber(v).getLong())); + put("fire", (e, v) -> e.setRemainingFireTicks((int) NumericValue.asNumber(v).getLong())); + put("frost", (e, v) -> e.setTicksFrozen((int) NumericValue.asNumber(v).getLong())); - put("hunger", (e, v)-> { - if(e instanceof Player) ((Player) e).getFoodData().setFoodLevel((int) NumericValue.asNumber(v).getLong()); + put("hunger", (e, v) -> { + if (e instanceof final Player p) + { + p.getFoodData().setFoodLevel((int) NumericValue.asNumber(v).getLong()); + } }); - put("exhaustion", (e, v)-> { - if(e instanceof Player) ((Player) e).getFoodData().setExhaustion(NumericValue.asNumber(v).getFloat()); + put("exhaustion", (e, v) -> { + if (e instanceof final Player p) + { + p.getFoodData().setExhaustion(NumericValue.asNumber(v).getFloat()); + } }); - put("add_exhaustion", (e, v)-> { - if (e instanceof Player) ((Player) e).getFoodData().addExhaustion(NumericValue.asNumber(v).getFloat()); + put("add_exhaustion", (e, v) -> { + if (e instanceof final Player p) + { + p.getFoodData().addExhaustion(NumericValue.asNumber(v).getFloat()); + } }); put("absorption", (e, v) -> { - if (e instanceof Player) ((Player) e).setAbsorptionAmount(NumericValue.asNumber(v, "absorbtion").getFloat()); + if (e instanceof final Player p) + { + p.setAbsorptionAmount(NumericValue.asNumber(v, "absorbtion").getFloat()); + } }); put("add_xp", (e, v) -> { - if (e instanceof Player) ((Player) e).giveExperiencePoints(NumericValue.asNumber(v, "add_xp").getInt()); + if (e instanceof final Player p) + { + p.giveExperiencePoints(NumericValue.asNumber(v, "add_xp").getInt()); + } }); put("xp_level", (e, v) -> { - if (e instanceof Player) ((Player) e).giveExperienceLevels(NumericValue.asNumber(v, "xp_level").getInt()-((Player) e).experienceLevel); + if (e instanceof final Player p) + { + p.giveExperienceLevels(NumericValue.asNumber(v, "xp_level").getInt() - p.experienceLevel); + } }); put("xp_progress", (e, v) -> { - if (e instanceof ServerPlayer) + if (e instanceof final ServerPlayer p) { - ServerPlayer p = (ServerPlayer) e; p.experienceProgress = NumericValue.asNumber(v, "xp_progress").getFloat(); p.connection.send(new ClientboundSetExperiencePacket(p.experienceProgress, p.totalExperience, p.experienceLevel)); } }); put("xp_score", (e, v) -> { - if (e instanceof Player) ((Player) e).setScore(NumericValue.asNumber(v, "xp_score").getInt()); + if (e instanceof final Player p) + { + p.setScore(NumericValue.asNumber(v, "xp_score").getInt()); + } }); - put("saturation", (e, v)-> { - if(e instanceof Player) ((Player) e).getFoodData().setSaturation(NumericValue.asNumber(v, "saturation").getFloat()); + put("saturation", (e, v) -> { + if (e instanceof final Player p) + { + p.getFoodData().setSaturation(NumericValue.asNumber(v, "saturation").getFloat()); + } }); put("air", (e, v) -> e.setAirSupply(NumericValue.asNumber(v, "air").getInt())); put("breaking_progress", (e, a) -> { - if (e instanceof ServerPlayer) + if (e instanceof final ServerPlayer sp) { - int progress = (a == null || a.isNull())?-1:NumericValue.asNumber(a).getInt(); - ServerPlayerInteractionManagerInterface manager = (ServerPlayerInteractionManagerInterface) (((ServerPlayer) e).gameMode); + final int progress = (a == null || a.isNull()) ? -1 : NumericValue.asNumber(a).getInt(); + final ServerPlayerInteractionManagerInterface manager = (ServerPlayerInteractionManagerInterface) (sp.gameMode); manager.setBlockBreakingProgress(progress); } }); @@ -1660,11 +1679,11 @@ public class EntityValue extends Value put("nbt", (e, v) -> { if (!(e instanceof Player)) { - UUID uUID = e.getUUID(); - Value tagValue = NBTSerializableValue.fromValue(v); - if (tagValue instanceof NBTSerializableValue) + final UUID uUID = e.getUUID(); + final Value tagValue = NBTSerializableValue.fromValue(v); + if (tagValue instanceof final NBTSerializableValue nbtsv) { - e.load(((NBTSerializableValue) tagValue).getCompoundTag()); + e.load(nbtsv.getCompoundTag()); e.setUUID(uUID); } } @@ -1672,56 +1691,67 @@ public class EntityValue extends Value put("nbt_merge", (e, v) -> { if (!(e instanceof Player)) { - UUID uUID = e.getUUID(); - Value tagValue = NBTSerializableValue.fromValue(v); - if (tagValue instanceof NBTSerializableValue) + final UUID uUID = e.getUUID(); + final Value tagValue = NBTSerializableValue.fromValue(v); + if (tagValue instanceof final NBTSerializableValue nbtsv) { - CompoundTag nbttagcompound = e.saveWithoutId((new CompoundTag())); - nbttagcompound.merge(((NBTSerializableValue) tagValue).getCompoundTag()); + final CompoundTag nbttagcompound = e.saveWithoutId((new CompoundTag())); + nbttagcompound.merge(nbtsv.getCompoundTag()); e.load(nbttagcompound); e.setUUID(uUID); } } }); - put("blue_skull",(e,v)->{ - if (e instanceof WitherSkull w){ + put("blue_skull", (e, v) -> { + if (e instanceof final WitherSkull w) + { w.setDangerous(v.getBoolean()); } - + }); - put("offering_flower",(e,v)->{ - if (e instanceof IronGolem ig){ + put("offering_flower", (e, v) -> { + if (e instanceof final IronGolem ig) + { ig.offerFlower(v.getBoolean()); } - + }); put("item", (e, v) -> { - ItemStack item=ValueConversions.getItemStackFromValue(v, true, e.level.registryAccess()); - if(e instanceof ItemEntity itementity) - itementity.setItem(item); - if(e instanceof ItemFrame itemframe) - itemframe.setItem(item); + final ItemStack item = ValueConversions.getItemStackFromValue(v, true, e.level.registryAccess()); + if (e instanceof final ItemEntity itementity) + { + itementity.setItem(item); + } + if (e instanceof final ItemFrame itemframe) + { + itemframe.setItem(item); + } }); // "dimension" [] // "count", [] // "effect_"name [] }}; - public void setEvent(CarpetContext cc, String eventName, FunctionValue fun, List args) + public void setEvent(final CarpetContext cc, final String eventName, final FunctionValue fun, final List args) { - EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName); + final EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName); if (event == null) + { throw new InternalExpressionException("Unknown entity event: " + eventName); - ((EntityInterface)getEntity()).getEventContainer().addEvent(event, cc.host, fun, args); + } + ((EntityInterface) getEntity()).getEventContainer().addEvent(event, cc.host, fun, args); } @Override - public net.minecraft.nbt.Tag toTag(boolean force) + public net.minecraft.nbt.Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); - CompoundTag tag = new CompoundTag(); - tag.put("Data", getEntity().saveWithoutId( new CompoundTag())); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } + final CompoundTag tag = new CompoundTag(); + tag.put("Data", getEntity().saveWithoutId(new CompoundTag())); final Registry> reg = getEntity().level.registryAccess().registryOrThrow(Registries.ENTITY_TYPE); tag.put("Name", StringTag.valueOf(reg.getKey(getEntity().getType()).toString())); return tag; diff --git a/src/main/java/carpet/script/value/FormattedTextValue.java b/src/main/java/carpet/script/value/FormattedTextValue.java index 815ad318..d55e3190 100644 --- a/src/main/java/carpet/script/value/FormattedTextValue.java +++ b/src/main/java/carpet/script/value/FormattedTextValue.java @@ -9,51 +9,56 @@ import net.minecraft.network.chat.MutableComponent; public class FormattedTextValue extends StringValue { Component text; - public FormattedTextValue(Component text) + + public FormattedTextValue(final Component text) { super(null); this.text = text; } - public static Value combine(Value left, Value right) { - MutableComponent text; - if (left instanceof FormattedTextValue) + public static Value combine(final Value left, final Value right) + { + final MutableComponent text; + if (left instanceof final FormattedTextValue ftv) { - text = ((FormattedTextValue) left).getText().copy(); + text = ftv.getText().copy(); } else { if (left.isNull()) + { return right; + } text = Component.literal(left.getString()); } - - if (right instanceof FormattedTextValue) - { - text.append(((FormattedTextValue) right).getText().copy()); - return new FormattedTextValue(text); - } - else - { - if (right.isNull()) - return left; - text.append(right.getString()); - return new FormattedTextValue(text); - } - } - public static Value of(Component text) { - if (text == null) return Value.NULL; + if (right instanceof final FormattedTextValue ftv) + { + text.append(ftv.getText().copy()); + return new FormattedTextValue(text); + } + if (right.isNull()) + { + return left; + } + text.append(right.getString()); return new FormattedTextValue(text); } + public static Value of(final Component text) + { + return text == null ? Value.NULL : new FormattedTextValue(text); + } + @Override - public String getString() { + public String getString() + { return text.getString(); } @Override - public boolean getBoolean() { + public boolean getBoolean() + { return !text.getString().isEmpty(); } @@ -75,19 +80,24 @@ public class FormattedTextValue extends StringValue } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } return StringTag.valueOf(Component.Serializer.toJson(text)); } @Override - public JsonElement toJson() { + public JsonElement toJson() + { return Component.Serializer.toJsonTree(text); } @Override - public Value add(Value o) { + public Value add(final Value o) + { return combine(this, o); } @@ -96,13 +106,14 @@ public class FormattedTextValue extends StringValue return Component.Serializer.toJson(text); } - public static FormattedTextValue deserialize(String serialized) + public static FormattedTextValue deserialize(final String serialized) { return new FormattedTextValue(Component.Serializer.fromJson(serialized)); } - public static Component getTextByValue(Value value) { - return (value instanceof FormattedTextValue) ? ((FormattedTextValue) value).getText() : Component.literal(value.getString()); + public static Component getTextByValue(final Value value) + { + return (value instanceof final FormattedTextValue ftv) ? ftv.getText() : Component.literal(value.getString()); } } diff --git a/src/main/java/carpet/script/value/FrameworkValue.java b/src/main/java/carpet/script/value/FrameworkValue.java index a432974e..c1987711 100644 --- a/src/main/java/carpet/script/value/FrameworkValue.java +++ b/src/main/java/carpet/script/value/FrameworkValue.java @@ -29,7 +29,7 @@ public abstract class FrameworkValue extends Value } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { throw new UnsupportedOperationException("Scarpet language component cannot be serialized to the tag"); } diff --git a/src/main/java/carpet/script/value/FunctionAnnotationValue.java b/src/main/java/carpet/script/value/FunctionAnnotationValue.java index 41ba7914..83b8f2f1 100644 --- a/src/main/java/carpet/script/value/FunctionAnnotationValue.java +++ b/src/main/java/carpet/script/value/FunctionAnnotationValue.java @@ -9,11 +9,15 @@ public class FunctionAnnotationValue extends Value { GLOBAL, VARARG } + public Type type; - public FunctionAnnotationValue(Value variable, Type type) + + public FunctionAnnotationValue(final Value variable, final Type type) { if (variable.boundVariable == null) + { throw new InternalExpressionException("You can only borrow variables from the outer scope"); + } this.boundVariable = variable.boundVariable; this.type = type; } @@ -37,7 +41,7 @@ public class FunctionAnnotationValue extends Value } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { throw new UnsupportedOperationException("Global value cannot be serialized to the tag"); } diff --git a/src/main/java/carpet/script/value/FunctionSignatureValue.java b/src/main/java/carpet/script/value/FunctionSignatureValue.java index e1c2f148..59ed5290 100644 --- a/src/main/java/carpet/script/value/FunctionSignatureValue.java +++ b/src/main/java/carpet/script/value/FunctionSignatureValue.java @@ -9,23 +9,21 @@ public class FunctionSignatureValue extends FrameworkValue private List globals; private String varArgs; - public FunctionSignatureValue(String name, List args, String varArgs, List globals) + public FunctionSignatureValue(final String name, final List args, final String varArgs, final List globals) { this.identifier = name; this.arguments = args; this.varArgs = varArgs; this.globals = globals; } - public String getName() + public String identifier() { return identifier; } - public List getArgs() + public List arguments() { return arguments; } - public List getGlobals() {return globals;} - - - public String getVarArgs() { return varArgs;} + public List globals() {return globals;} + public String varArgs() { return varArgs;} } diff --git a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java index e33a64eb..4e00ecc9 100644 --- a/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java +++ b/src/main/java/carpet/script/value/FunctionUnpackedArgumentsValue.java @@ -4,7 +4,8 @@ import java.util.List; public class FunctionUnpackedArgumentsValue extends ListValue { - public FunctionUnpackedArgumentsValue(List list) { + public FunctionUnpackedArgumentsValue(final List list) + { super(list); } @@ -17,7 +18,6 @@ public class FunctionUnpackedArgumentsValue extends ListValue @Override public Value deepcopy() { - ListValue copy = (ListValue)super.deepcopy(); - return new FunctionUnpackedArgumentsValue(copy.items); + return new FunctionUnpackedArgumentsValue(((ListValue) super.deepcopy()).items); } } diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index d7147137..8ee3780d 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -12,12 +12,14 @@ import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; import carpet.script.exception.ReturnStatement; + import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Consumer; import java.util.stream.Collectors; + import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; @@ -33,7 +35,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction private static long variantCounter = 1; private long variant; - private FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List args, String varArgs) + private FunctionValue(final Expression expression, final Tokenizer.Token token, final String name, final LazyValue body, final List args, final String varArgs) { this.expression = expression; this.token = token; @@ -45,7 +47,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction variant = 0L; } - public FunctionValue(Expression expression, Tokenizer.Token token, String name, LazyValue body, List args, String varArgs, Map outerState) + public FunctionValue(final Expression expression, final Tokenizer.Token token, final String name, final LazyValue body, final List args, final String varArgs, final Map outerState) { this.expression = expression; this.token = token; @@ -63,19 +65,27 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return name; } - public Module getModule() {return expression.module;} + public Module getModule() + { + return expression.module; + } @Override public String getPrettyString() { - List stringArgs= new ArrayList<>(args); + final List stringArgs = new ArrayList<>(args); if (outerState != null) + { stringArgs.addAll(outerState.entrySet().stream().map(e -> - "outer("+e.getKey()+") = "+e.getValue().evalValue(null).getPrettyString()).collect(Collectors.toList())); - return (name.equals("_")?"":name) +"("+String.join(", ",stringArgs)+")"; + "outer(" + e.getKey() + ") = " + e.getValue().evalValue(null).getPrettyString()).toList()); + } + return (name.equals("_") ? "" : name) + "(" + String.join(", ", stringArgs) + ")"; } - public String fullName() {return (name.equals("_")?"":name)+(expression.module == null?"":"["+expression.module.name()+"]");} + public String fullName() + { + return (name.equals("_") ? "" : name) + (expression.module == null ? "" : "[" + expression.module.name() + "]"); + } @Override public boolean getBoolean() @@ -86,7 +96,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction @Override protected Value clone() { - FunctionValue ret = new FunctionValue(expression, token, name, body, args, varArgs); + final FunctionValue ret = new FunctionValue(expression, token, name, body, args, varArgs); ret.outerState = this.outerState; ret.variant = this.variant; return ret; @@ -95,26 +105,22 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction @Override public int hashCode() { - return name.hashCode()+(int)variant; + return name.hashCode() + (int) variant; } @Override - public boolean equals(Object o) + public boolean equals(final Object o) { - if (o instanceof FunctionValue) - return name.equals(((FunctionValue) o).name) && variant == ((FunctionValue) o).variant; - return false; + return o instanceof final FunctionValue fv && name.equals(fv.name) && variant == fv.variant; } @Override public int compareTo(final Value o) { - if (o instanceof FunctionValue) + if (o instanceof final FunctionValue fv) { - int nameSame = this.name.compareTo(((FunctionValue) o).name); - if (nameSame != 0) - return nameSame; - return (int) (variant-((FunctionValue) o).variant); + final int nameSame = this.name.compareTo(fv.name); + return nameSame != 0 ? nameSame : (int) (variant - fv.variant); } return getString().compareTo(o.getString()); } @@ -132,7 +138,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction } @Override - public Value slice(long from, Long to) + public Value slice(final long from, final Long to) { throw new InternalExpressionException("Cannot slice a function"); } @@ -149,46 +155,49 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return varArgs != null; } - public LazyValue callInContext(Context c, Context.Type type, List params) + public LazyValue callInContext(final Context c, final Context.Type type, final List params) { try { return execute(c, type, expression, token, params); } - catch (ExpressionException exc) + catch (final ExpressionException exc) { exc.stack.add(this); throw exc; } - catch (InternalExpressionException exc) + catch (final InternalExpressionException exc) { exc.stack.add(this); throw new ExpressionException(c, expression, token, exc.getMessage(), exc.stack); } - - catch (ArithmeticException exc) + catch (final ArithmeticException exc) { - throw new ExpressionException(c, expression, token, "Your math is wrong, "+exc.getMessage(), Collections.singletonList(this)); + throw new ExpressionException(c, expression, token, "Your math is wrong, " + exc.getMessage(), Collections.singletonList(this)); } } - public void checkArgs(int candidates) + public void checkArgs(final int candidates) { - int actual = getArguments().size(); + final int actual = getArguments().size(); if (candidates < actual) + { throw new InternalExpressionException("Function " + getPrettyString() + " requires at least " + actual + " arguments"); + } if (candidates > actual && getVarArgs() == null) + { throw new InternalExpressionException("Function " + getPrettyString() + " requires " + actual + " arguments"); + } } - public static List unpackArgs(List lazyParams, Context c) + public static List unpackArgs(final List lazyParams, final Context c) { // TODO we shoudn't need that if all fuctions are not lazy really - List params = new ArrayList<>(); - for (LazyValue lv : lazyParams) + final List params = new ArrayList<>(); + for (final LazyValue lv : lazyParams) { - Value param = lv.evalValue(c, Context.NONE); + final Value param = lv.evalValue(c, Context.NONE); if (param instanceof FunctionUnpackedArgumentsValue) { CarpetSettings.LOG.error("How did we get here?"); @@ -203,48 +212,51 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction } @Override - public LazyValue lazyEval(Context c, Context.Type type, Expression e, Tokenizer.Token t, List lazyParams) { - List resolvedParams = unpackArgs(lazyParams, c); + public LazyValue lazyEval(final Context c, final Context.Type type, final Expression e, final Tokenizer.Token t, final List lazyParams) + { + final List resolvedParams = unpackArgs(lazyParams, c); return execute(c, type, e, t, resolvedParams); } - public LazyValue execute(Context c, Context.Type type, Expression e, Tokenizer.Token t, List params) + public LazyValue execute(final Context c, final Context.Type type, final Expression e, final Tokenizer.Token t, final List params) { - assertArgsOk(params, (fixedArgs) ->{ + assertArgsOk(params, fixedArgs -> { if (fixedArgs) // wrong number of args for fixed args { throw new ExpressionException(c, e, t, - "Incorrect number of arguments for function "+name+ - ". Should be "+args.size()+", not "+params.size()+" like "+args + "Incorrect number of arguments for function " + name + + ". Should be " + args.size() + ", not " + params.size() + " like " + args ); } - else // too few args for varargs - { - List argList = new ArrayList<>(args); - argList.add("... "+varArgs); - throw new ExpressionException(c, e, t, - "Incorrect number of arguments for function "+name+ - ". Should be at least "+args.size()+", not "+params.size()+" like "+argList - ); - } - }); - Context newFrame = c.recreate(); + // too few args for varargs - if (outerState != null) outerState.forEach(newFrame::setVariable); - for (int i=0; i argList = new ArrayList<>(args); + argList.add("... " + varArgs); + throw new ExpressionException(c, e, t, + "Incorrect number of arguments for function " + name + + ". Should be at least " + args.size() + ", not " + params.size() + " like " + argList + ); + }); + final Context newFrame = c.recreate(); + + if (outerState != null) { - String arg = args.get(i); - Value val = params.get(i).reboundedTo(arg); // todo check if we need to copy that + outerState.forEach(newFrame::setVariable); + } + for (int i = 0; i < args.size(); i++) + { + final String arg = args.get(i); + final Value val = params.get(i).reboundedTo(arg); // todo check if we need to copy that newFrame.setVariable(arg, (cc, tt) -> val); } if (varArgs != null) { - List extraParams = new ArrayList<>(); + final List extraParams = new ArrayList<>(); for (int i = args.size(), mx = params.size(); i < mx; i++) { extraParams.add(params.get(i).reboundedTo(null)); // copy by value I guess } - Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that? + final Value rest = ListValue.wrap(extraParams).bindTo(varArgs); // didn't we just copied that? newFrame.setVariable(varArgs, (cc, tt) -> rest); } @@ -253,15 +265,15 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction { retVal = body.evalValue(newFrame, type); // todo not sure if we need to propagete type / consider boolean context in defined functions - answer seems ye } - catch (BreakStatement | ContinueStatement exc) + catch (final BreakStatement | ContinueStatement exc) { throw new ExpressionException(c, e, t, "'continue' and 'break' can only be called inside loop function bodies"); } - catch (ReturnStatement returnStatement) + catch (final ReturnStatement returnStatement) { retVal = returnStatement.retval; } - Value otherRetVal = retVal; + final Value otherRetVal = retVal; return (cc, tt) -> otherRetVal; } @@ -269,30 +281,38 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction { return expression; } + public Tokenizer.Token getToken() { return token; } + public List getArguments() { return args; } - public String getVarArgs() {return varArgs; } + + public String getVarArgs() + { + return varArgs; + } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } return StringTag.valueOf(getString()); } - public void assertArgsOk(List list, Consumer feedback) + public void assertArgsOk(final List list, final Consumer feedback) { - int size = list.size(); + final int size = list.size(); if (varArgs == null && args.size() != size) // wrong number of args for fixed args { feedback.accept(true); - } else if (varArgs != null && args.size() > size) // too few args for varargs { @@ -301,12 +321,14 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction } @Override - public boolean pure() { + public boolean pure() + { return false; } @Override - public boolean transitive() { + public boolean transitive() + { return false; } } diff --git a/src/main/java/carpet/script/value/LContainerValue.java b/src/main/java/carpet/script/value/LContainerValue.java index 2c46ee55..60471264 100644 --- a/src/main/java/carpet/script/value/LContainerValue.java +++ b/src/main/java/carpet/script/value/LContainerValue.java @@ -2,16 +2,23 @@ package carpet.script.value; public class LContainerValue extends FrameworkValue { - private ContainerValueInterface container; - private Value address; + private final ContainerValueInterface container; + private final Value address; public static final LContainerValue NULL_CONTAINER = new LContainerValue(null, null); - public LContainerValue(ContainerValueInterface c, Value v) + public LContainerValue(final ContainerValueInterface c, final Value v) { container = c; address = v; } - public ContainerValueInterface getContainer() {return container; } - public Value getAddress() {return address; } + public ContainerValueInterface container() + { + return container; + } + + public Value address() + { + return address; + } } diff --git a/src/main/java/carpet/script/value/LazyListValue.java b/src/main/java/carpet/script/value/LazyListValue.java index 9c93139d..00dc9cf0 100644 --- a/src/main/java/carpet/script/value/LazyListValue.java +++ b/src/main/java/carpet/script/value/LazyListValue.java @@ -1,35 +1,41 @@ package carpet.script.value; import carpet.script.exception.InternalExpressionException; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; + import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; public abstract class LazyListValue extends AbstractListValue implements Iterator { - public static LazyListValue rangeDouble(double from, double to, double step) + public static LazyListValue rangeDouble(final double from, final double to, final double step) { return new LazyListValue() { { if (step == 0) + { throw new InternalExpressionException("Range will never end with a zero step"); + } this.start = from; this.current = this.start; this.limit = to; this.stepp = step; } + private final double start; private double current; private final double limit; private final double stepp; + @Override public Value next() { - Value val = new NumericValue(current); + final Value val = new NumericValue(current); current += stepp; return val; } @@ -43,36 +49,41 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato @Override public boolean hasNext() { - return stepp > 0?(current < limit):(current > limit); + return stepp > 0 ? (current < limit) : (current > limit); } @Override public String getString() { - return String.format(Locale.ROOT, "[%s, %s, ..., %s)",NumericValue.of(start).getString(), NumericValue.of(start+stepp).getString(), NumericValue.of( limit).getString()); + return String.format(Locale.ROOT, "[%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString()); } }; } - public static LazyListValue rangeLong(long from, long to, long step) + + public static LazyListValue rangeLong(final long from, final long to, final long step) { return new LazyListValue() { { if (step == 0) + { throw new InternalExpressionException("Range will never end with a zero step"); + } this.start = from; this.current = this.start; this.limit = to; this.stepp = step; } + private final long start; private long current; private final long limit; private final long stepp; + @Override public Value next() { - Value val = new NumericValue(current); + final Value val = new NumericValue(current); current += stepp; return val; } @@ -86,13 +97,13 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato @Override public boolean hasNext() { - return stepp > 0?(current < limit):(current > limit); + return stepp > 0 ? (current < limit) : (current > limit); } @Override public String getString() { - return String.format(Locale.ROOT, "[%s, %s, ..., %s)",NumericValue.of(start).getString(), NumericValue.of(start+stepp).getString(), NumericValue.of( limit).getString()); + return String.format(Locale.ROOT, "[%s, %s, ..., %s)", NumericValue.of(start).getString(), NumericValue.of(start + stepp).getString(), NumericValue.of(limit).getString()); } }; } @@ -108,20 +119,24 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato { return hasNext(); } - @Override public abstract boolean hasNext(); - - @Override public abstract Value next(); @Override - public void fatality() {reset();} + public void fatality() + { + reset(); + } + public abstract void reset(); @Override - public Iterator iterator() {return this;} + public Iterator iterator() + { + return this; + } public List unroll() { - List result = new ArrayList<>(); + final List result = new ArrayList<>(); this.forEachRemaining(result::add); fatality(); return result; @@ -130,26 +145,38 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato @Override public Value slice(long from, Long to) { - if (to == null || to < 0) to = (long) Integer.MAX_VALUE; - if (from < 0) from = 0; + if (to == null || to < 0) + { + to = (long) Integer.MAX_VALUE; + } + if (from < 0) + { + from = 0; + } if (from > to) + { return ListValue.of(); - List result = new ArrayList<>(); + } + final List result = new ArrayList<>(); int i; for (i = 0; i < from; i++) { if (hasNext()) + { next(); + } else { fatality(); return ListValue.wrap(result); } } - for (i = (int)from; i < to; i++) + for (i = (int) from; i < to; i++) { if (hasNext()) + { result.add(next()); + } else { fatality(); @@ -158,8 +185,9 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato } return ListValue.wrap(result); } + @Override - public Value add(Value other) + public Value add(final Value other) { throw new InternalExpressionException("Cannot add to iterators"); } @@ -175,37 +203,42 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato { return "iterator"; } + @Override public Object clone() { - Object copy; + final Object copy; try { copy = super.clone(); } - catch (CloneNotSupportedException e) + catch (final CloneNotSupportedException e) { throw new InternalExpressionException("Cannot copy iterators"); } - ((LazyListValue)copy).reset(); + ((LazyListValue) copy).reset(); return copy; } @Override - public Value fromConstant() { - return (Value)clone(); + public Value fromConstant() + { + return (Value) clone(); } @Override public int hashCode() { - return ("i"+getString()).hashCode(); + return ("i" + getString()).hashCode(); } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } return StringTag.valueOf(getString()); } } diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index 3fd16e3a..f31fa111 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -4,6 +4,7 @@ import carpet.script.LazyValue; import carpet.script.exception.InternalExpressionException; import com.google.gson.JsonArray; import com.google.gson.JsonElement; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -14,6 +15,7 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; + import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.IntTag; @@ -28,23 +30,24 @@ import static java.lang.Math.abs; public class ListValue extends AbstractListValue implements ContainerValueInterface { protected final List items; + @Override public String getString() { - return "["+items.stream().map(Value::getString).collect(Collectors.joining(", "))+"]"; + return "[" + items.stream().map(Value::getString).collect(Collectors.joining(", ")) + "]"; } @Override public String getPrettyString() { - if (items.size()<8) - return "["+items.stream().map(Value::getPrettyString).collect(Collectors.joining(", "))+"]"; - return "["+items.get(0).getPrettyString()+", "+items.get(1).getPrettyString()+", ..., "+ - items.get(items.size()-2).getPrettyString()+", "+items.get(items.size()-1).getPrettyString()+"]"; + return items.size() < 8 + ? "[" + items.stream().map(Value::getPrettyString).collect(Collectors.joining(", ")) + "]" + : "[" + items.get(0).getPrettyString() + ", " + items.get(1).getPrettyString() + ", ..., " + items.get(items.size() - 2).getPrettyString() + ", " + items.get(items.size() - 1).getPrettyString() + "]"; } @Override - public boolean getBoolean() { + public boolean getBoolean() + { return !items.isEmpty(); } @@ -57,56 +60,63 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf @Override public Value deepcopy() { - List copyItems = new ArrayList<>(items.size()); - for (Value entry: items) copyItems.add(entry.deepcopy()); + final List copyItems = new ArrayList<>(items.size()); + for (final Value entry : items) + { + copyItems.add(entry.deepcopy()); + } return new ListValue(copyItems); } - public ListValue(Collection list) + public ListValue(final Collection list) { items = new ArrayList<>(list); } - protected ListValue(List list) + protected ListValue(final List list) { items = list; } - public static Value fromTriple(double a, double b, double c) + public static Value fromTriple(final double a, final double b, final double c) { return ListValue.of(new NumericValue(a), new NumericValue(b), new NumericValue(c)); } - public static Value fromTriple(int a, int b, int c) + public static Value fromTriple(final int a, final int b, final int c) { return fromTriple((double) a, b, c); } - public static ListValue wrap(Stream stream) + public static ListValue wrap(final Stream stream) { return wrap(stream.collect(Collectors.toList())); } - public static ListValue wrap(List list) + public static ListValue wrap(final List list) { return new ListValue(list); } - public static ListValue of(Value ... list) + + public static ListValue of(final Value... list) { return new ListValue(new ArrayList<>(Arrays.asList(list))); } - public static ListValue ofNums(Number ... list) + + public static ListValue ofNums(final Number... list) { - List valList = new ArrayList<>(); - for (Number i : list) + final List valList = new ArrayList<>(); + for (final Number i : list) + { valList.add(new NumericValue(i.doubleValue())); + } return new ListValue(valList); } public static LazyValue lazyEmpty() { - Value ret = new ListValue(); + final Value ret = new ListValue(); return (c, t) -> ret; } @@ -116,16 +126,17 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value add(Value other) { - ListValue output = new ListValue(); - if (other instanceof ListValue) + public Value add(final Value other) + { + final ListValue output = new ListValue(); + if (other instanceof final ListValue list) { - List other_list = ((ListValue) other).items; - if (other_list.size() == items.size()) + final List otherItems = list.items; + if (otherItems.size() == items.size()) { - for(int i = 0, size = items.size(); i < size; i++) + for (int i = 0, size = items.size(); i < size; i++) { - output.items.add(items.get(i).add(other_list.get(i))); + output.items.add(items.get(i).add(otherItems.get(i))); } } else @@ -135,31 +146,32 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - for (Value v : items) + for (final Value v : items) { output.items.add(v.add(other)); } } return output; } + @Override - public void append(Value v) + public void append(final Value v) { items.add(v); } @Override - public Value subtract(Value other) + public Value subtract(final Value other) { - ListValue output = new ListValue(); - if (other instanceof ListValue) + final ListValue output = new ListValue(); + if (other instanceof final ListValue list) { - List other_list = ((ListValue) other).items; - if (other_list.size() == items.size()) + final List otherItems = list.items; + if (otherItems.size() == items.size()) { - for(int i = 0, size = items.size(); i < size; i++) + for (int i = 0, size = items.size(); i < size; i++) { - output.items.add(items.get(i).subtract(other_list.get(i))); + output.items.add(items.get(i).subtract(otherItems.get(i))); } } else @@ -169,31 +181,32 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - for (Value v : items) + for (final Value v : items) { output.items.add(v.subtract(other)); } } return output; } - public void subtractFrom(Value v) // if I ever do -= then it wouod remove items + + public void subtractFrom(final Value v) // if I ever do -= then it wouod remove items { throw new UnsupportedOperationException(); // TODO } @Override - public Value multiply(Value other) + public Value multiply(final Value other) { - ListValue output = new ListValue(); - if (other instanceof ListValue) + final ListValue output = new ListValue(); + if (other instanceof final ListValue list) { - List other_list = ((ListValue) other).items; - if (other_list.size() == items.size()) + final List otherItems = list.items; + if (otherItems.size() == items.size()) { - for(int i = 0, size = items.size(); i < size; i++) + for (int i = 0, size = items.size(); i < size; i++) { - output.items.add(items.get(i).multiply(other_list.get(i))); + output.items.add(items.get(i).multiply(otherItems.get(i))); } } else @@ -203,7 +216,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - for (Value v : items) + for (final Value v : items) { output.items.add(v.multiply(other)); } @@ -212,17 +225,17 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value divide(Value other) + public Value divide(final Value other) { - ListValue output = new ListValue(); - if (other instanceof ListValue) + final ListValue output = new ListValue(); + if (other instanceof final ListValue list) { - List other_list = ((ListValue) other).items; - if (other_list.size() == items.size()) + final List otherItems = list.items; + if (otherItems.size() == items.size()) { - for(int i = 0, size = items.size(); i < size; i++) + for (int i = 0, size = items.size(); i < size; i++) { - output.items.add(items.get(i).divide(other_list.get(i))); + output.items.add(items.get(i).divide(otherItems.get(i))); } } else @@ -232,7 +245,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - for (Value v : items) + for (final Value v : items) { output.items.add(v.divide(other)); } @@ -241,19 +254,27 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public int compareTo(Value o) + public int compareTo(final Value o) { - if (o instanceof ListValue) + if (o instanceof final ListValue ol) { - ListValue ol = (ListValue)o; - int this_size = this.getItems().size(); - int o_size = ol.getItems().size(); - if (this_size != o_size) return this_size - o_size; - if (this_size == 0) return 0; - for (int i = 0; i < this_size; i++) + final int size = this.getItems().size(); + final int otherSize = ol.getItems().size(); + if (size != otherSize) { - int res = this.items.get(i).compareTo(ol.items.get(i)); - if (res != 0) return res; + return size - otherSize; + } + if (size == 0) + { + return 0; + } + for (int i = 0; i < size; i++) + { + final int res = this.items.get(i).compareTo(ol.items.get(i)); + if (res != 0) + { + return res; + } } return 0; } @@ -263,11 +284,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf @Override public boolean equals(final Object o) { - if (o instanceof ListValue) - { - return getItems().equals(((ListValue) o).getItems()); - } - return false; + return o instanceof final ListValue list && getItems().equals(list.getItems()); } public List getItems() @@ -276,7 +293,10 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Iterator iterator() { return new ArrayList<>(items).iterator(); } // should be thread safe + public Iterator iterator() + { + return new ArrayList<>(items).iterator(); + } // should be thread safe @Override public List unpack() @@ -284,7 +304,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf return new ArrayList<>(items); } - public void extend(List subList) + public void extend(final List subList) { items.addAll(subList); } @@ -296,18 +316,21 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf * @param len * @return */ - public static int normalizeIndex(long idx, int len) + public static int normalizeIndex(long idx, final int len) { - if (idx >=0 && idx < len) return (int)idx; - long range = abs(idx)/len; - idx += (range+2)*len; + if (idx >= 0 && idx < len) + { + return (int) idx; + } + final long range = abs(idx) / len; + idx += (range + 2) * len; idx = idx % len; - return (int)idx; + return (int) idx; } public static class ListConstructorValue extends ListValue { - public ListConstructorValue(Collection list) + public ListConstructorValue(final Collection list) { super(list); } @@ -320,11 +343,11 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value in(Value value1) + public Value in(final Value value1) { for (int i = 0; i < items.size(); i++) { - Value v = items.get(i); + final Value v = items.get(i); if (v.equals(value1)) { return new NumericValue(i); @@ -334,22 +357,27 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value slice(long fromDesc, Long toDesc) + public Value slice(final long fromDesc, final Long toDesc) { - List items = getItems(); - int size = items.size(); - int from = normalizeIndex(fromDesc, size); + final List items = getItems(); + final int size = items.size(); + final int from = normalizeIndex(fromDesc, size); if (toDesc == null) + { return new ListValue(new ArrayList<>(getItems().subList(from, size))); - int to = normalizeIndex(toDesc, size+1); + } + final int to = normalizeIndex(toDesc, size + 1); if (from > to) + { return ListValue.of(); + } return new ListValue(new ArrayList<>(getItems().subList(from, to))); } @Override - public Value split(Value delimiter) { - ListValue result = new ListValue(); + public Value split(final Value delimiter) + { + final ListValue result = new ListValue(); if (delimiter == null) { this.forEach(item -> result.items.add(of(item))); @@ -357,12 +385,12 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } int startIndex = 0; int index = 0; - for (Value val : this.items) + for (final Value val : this.items) { index++; if (val.equals(delimiter)) { - result.items.add(new ListValue(new ArrayList<>(this.items.subList(startIndex, index-1)))); + result.items.add(new ListValue(new ArrayList<>(this.items.subList(startIndex, index - 1)))); startIndex = index; } } @@ -373,35 +401,41 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf @Override public double readDoubleNumber() { - return (double)items.size(); + return items.size(); } @Override - public boolean put(Value where, Value value, Value conditionValue) + public boolean put(final Value where, final Value value, final Value conditionValue) { - String condition = conditionValue.getString(); + final String condition = conditionValue.getString(); if (condition.equalsIgnoreCase("insert")) + { return put(where, value, false, false); + } if (condition.equalsIgnoreCase("extend")) + { return put(where, value, false, true); + } if (condition.equalsIgnoreCase("replace")) + { return put(where, value, true, false); - throw new InternalExpressionException("List 'put' modifier could be either 'insert', 'replace', or extend"); + } + throw new InternalExpressionException("List 'put' modifier could be either 'insert', 'replace', or extend"); } @Override - public boolean put(Value ind, Value value) + public boolean put(final Value ind, final Value value) { return put(ind, value, true, false); } - private boolean put(Value ind, Value value, boolean replace, boolean extend) + private boolean put(final Value ind, final Value value, final boolean replace, final boolean extend) { if (ind.isNull()) { if (extend && value instanceof AbstractListValue) { - ((AbstractListValue) value).iterator().forEachRemaining((v)-> items.add(v)); + ((AbstractListValue) value).iterator().forEachRemaining(items::add); } else { @@ -410,27 +444,35 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - int numitems = items.size(); + final int numitems = items.size(); if (!(ind instanceof NumericValue)) + { return false; - int index = (int)((NumericValue) ind).getLong(); + } + int index = (int) ((NumericValue) ind).getLong(); if (index < 0) {// only for values < 0 index = normalizeIndex(index, numitems); } if (replace) { - while (index >= items.size()) items.add(Value.NULL); + while (index >= items.size()) + { + items.add(Value.NULL); + } items.set(index, value); return true; } - while (index > items.size()) items.add(Value.NULL); + while (index > items.size()) + { + items.add(Value.NULL); + } if (extend && value instanceof AbstractListValue) { - Iterable iterable = ((AbstractListValue) value)::iterator; - List appendix = StreamSupport.stream( iterable.spliterator(), false).collect(Collectors.toList()); - items.addAll(index, appendix ); + final Iterable iterable = ((AbstractListValue) value)::iterator; + final List appendix = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); + items.addAll(index, appendix); return true; } items.add(index, value); @@ -439,25 +481,27 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value get(Value value) + public Value get(final Value value) { - int size = items.size(); - if (size == 0) return Value.NULL; - return items.get(normalizeIndex(NumericValue.asNumber(value, "'address' to a list index").getLong(), size)); + final int size = items.size(); + return size == 0 ? Value.NULL : items.get(normalizeIndex(NumericValue.asNumber(value, "'address' to a list index").getLong(), size)); } @Override - public boolean has(Value where) + public boolean has(final Value where) { - long index = NumericValue.asNumber(where, "'address' to a list index").getLong(); + final long index = NumericValue.asNumber(where, "'address' to a list index").getLong(); return index >= 0 && index < items.size(); } @Override - public boolean delete(Value where) + public boolean delete(final Value where) { - if (!(where instanceof NumericValue) || items.isEmpty()) return false; - long index = ((NumericValue) where).getLong(); + if (!(where instanceof NumericValue) || items.isEmpty()) + { + return false; + } + final long index = ((NumericValue) where).getLong(); items.remove(normalizeIndex(index, items.size())); return true; } @@ -482,35 +526,54 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf LIST, MAP, STRING; - private static TagTypeCompat getType(Tag tag) + + private static TagTypeCompat getType(final Tag tag) { - if (tag instanceof IntTag) return INT; - if (tag instanceof LongTag) return LONG; - if (tag instanceof DoubleTag) return DBL; - if (tag instanceof ListTag) return LIST; - if (tag instanceof CompoundTag) return MAP; + if (tag instanceof IntTag) + { + return INT; + } + if (tag instanceof LongTag) + { + return LONG; + } + if (tag instanceof DoubleTag) + { + return DBL; + } + if (tag instanceof ListTag) + { + return LIST; + } + if (tag instanceof CompoundTag) + { + return MAP; + } return STRING; } } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - int argSize = items.size(); - if (argSize == 0) return new ListTag(); - ListTag tag = new ListTag(); - if (argSize ==1) + final int argSize = items.size(); + if (argSize == 0) + { + return new ListTag(); + } + final ListTag tag = new ListTag(); + if (argSize == 1) { tag.add(items.get(0).toTag(force)); return tag; } // figuring out the types - List tags= new ArrayList<>(); + final List tags = new ArrayList<>(); items.forEach(v -> tags.add(v.toTag(force))); - Set cases = EnumSet.noneOf(TagTypeCompat.class); + final Set cases = EnumSet.noneOf(TagTypeCompat.class); tags.forEach(t -> cases.add(TagTypeCompat.getType(t))); - if (cases.size()==1) // well, one type of items + if (cases.size() == 1) // well, one type of items { tag.addAll(tags); return tag; @@ -519,28 +582,28 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf || cases.contains(TagTypeCompat.MAP) || cases.contains(TagTypeCompat.STRING)) // incompatible types { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } tags.forEach(t -> tag.add(StringTag.valueOf(t.getAsString()))); return tag; } // only numbers / mixed types - if (cases.contains(TagTypeCompat.DBL)) - { - tags.forEach(t -> tag.add(DoubleTag.valueOf(((NumericTag)t).getAsDouble()))); - } - else - { - tags.forEach(t -> tag.add(LongTag.valueOf(((NumericTag)t).getAsLong()))); - } + tags.forEach(cases.contains(TagTypeCompat.DBL) + ? (t -> tag.add(DoubleTag.valueOf(((NumericTag) t).getAsDouble()))) + : (t -> tag.add(LongTag.valueOf(((NumericTag) t).getAsLong())))); return tag; } @Override public JsonElement toJson() { - JsonArray array = new JsonArray(); - for (Value el: items) + final JsonArray array = new JsonArray(); + for (final Value el : items) + { array.add(el.toJson()); + } return array; } } diff --git a/src/main/java/carpet/script/value/MapValue.java b/src/main/java/carpet/script/value/MapValue.java index d9f173b9..95f75131 100644 --- a/src/main/java/carpet/script/value/MapValue.java +++ b/src/main/java/carpet/script/value/MapValue.java @@ -3,6 +3,7 @@ package carpet.script.value; import carpet.script.exception.InternalExpressionException; import com.google.gson.JsonElement; import com.google.gson.JsonObject; + import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -11,6 +12,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; + import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -23,22 +25,16 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa map = new HashMap<>(); } - public MapValue(List kvPairs) + public MapValue(final List kvPairs) { this(); - for (Value v : kvPairs) - { - put(v); - } + kvPairs.forEach(this::put); } - public MapValue(Set keySet) + public MapValue(final Set keySet) { this(); - for (Value v : keySet) - { - map.put(v, Value.NULL); - } + keySet.forEach(v -> map.put(v, Value.NULL)); } @Override @@ -56,20 +52,22 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa @Override public String getString() { - return "{"+map.entrySet().stream().map((p) -> p.getKey().getString()+": "+p.getValue().getString()).collect(Collectors.joining(", "))+"}"; + return "{" + map.entrySet().stream().map(p -> p.getKey().getString() + ": " + p.getValue().getString()).collect(Collectors.joining(", ")) + "}"; } @Override public String getPrettyString() { - if (map.size()<6) - return "{"+map.entrySet().stream().map((p) -> p.getKey().getPrettyString()+": "+p.getValue().getPrettyString()).collect(Collectors.joining(", "))+"}"; - List keys = new ArrayList<>(map.keySet()); - int max = keys.size(); - return "{"+keys.get(0).getPrettyString()+": "+map.get(keys.get(0)).getPrettyString()+", "+ - keys.get(1).getPrettyString()+": "+map.get(keys.get(1)).getPrettyString()+", ..., "+ - keys.get(max-2).getPrettyString()+": "+map.get(keys.get(max-2)).getPrettyString()+", "+ - keys.get(max-1).getPrettyString()+": "+map.get(keys.get(max-1)).getPrettyString()+"}"; + if (map.size() < 6) + { + return "{" + map.entrySet().stream().map(p -> p.getKey().getPrettyString() + ": " + p.getValue().getPrettyString()).collect(Collectors.joining(", ")) + "}"; + } + final List keys = new ArrayList<>(map.keySet()); + final int max = keys.size(); + return "{" + keys.get(0).getPrettyString() + ": " + map.get(keys.get(0)).getPrettyString() + ", " + + keys.get(1).getPrettyString() + ": " + map.get(keys.get(1)).getPrettyString() + ", ..., " + + keys.get(max - 2).getPrettyString() + ": " + map.get(keys.get(max - 2)).getPrettyString() + ", " + + keys.get(max - 1).getPrettyString() + ": " + map.get(keys.get(max - 1)).getPrettyString() + "}"; } @Override @@ -87,35 +85,34 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa @Override public Value deepcopy() { - Map copyMap = new HashMap<>(); + final Map copyMap = new HashMap<>(); map.forEach((key, value) -> copyMap.put(key.deepcopy(), value.deepcopy())); return new MapValue(copyMap); } - private MapValue(Map other) + private MapValue(final Map other) { map = other; } - public static MapValue wrap(Map other) + public static MapValue wrap(final Map other) { return new MapValue(other); } @Override - public Value add(Value o) + public Value add(final Value o) { - Map newItems = new HashMap<>(map); - if (o instanceof MapValue) + final Map newItems = new HashMap<>(map); + if (o instanceof final MapValue mapValue) { - newItems.putAll(((MapValue) o).map); + newItems.putAll(mapValue.map); } - else if (o instanceof AbstractListValue) + else if (o instanceof final AbstractListValue alv) { - Iterator it = ((AbstractListValue) o).iterator(); - while (it.hasNext()) + for (final Value value : alv) { - newItems.put(it.next(), Value.NULL); + newItems.put(value, Value.NULL); } } else @@ -126,31 +123,30 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa } @Override - public Value subtract(Value v) + public Value subtract(final Value v) { throw new InternalExpressionException("Cannot subtract from a map value"); } @Override - public Value multiply(Value v) + public Value multiply(final Value v) { throw new InternalExpressionException("Cannot multiply with a map value"); } @Override - public Value divide(Value v) + public Value divide(final Value v) { throw new InternalExpressionException("Cannot divide a map value"); } - public void put(Value v) + public void put(final Value v) { - if (!(v instanceof ListValue)) + if (!(v instanceof final ListValue pair)) { map.put(v, Value.NULL); return; } - ListValue pair = (ListValue)v; if (pair.getItems().size() != 2) { throw new InternalExpressionException("Map constructor requires elements that have two items"); @@ -159,13 +155,13 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa } @Override - public void append(Value v) + public void append(final Value v) { map.put(v, Value.NULL); } @Override - public int compareTo(Value o) + public int compareTo(final Value o) { throw new InternalExpressionException("Cannot compare with a map value"); } @@ -173,11 +169,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa @Override public boolean equals(final Object o) { - if (o instanceof MapValue) - { - return map.equals(((MapValue) o).map); - } - return false; + return o instanceof final MapValue mapValue && map.equals(mapValue.map); } public Map getMap() @@ -185,9 +177,9 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa return map; } - public void extend(List subList) + public void extend(final List subList) { - for (Value v: subList) put(v); + subList.forEach(this::put); } @Override @@ -197,53 +189,51 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa } @Override - public Value in(Value value1) + public Value in(final Value value) { - if (map.containsKey(value1)) return value1; - return Value.NULL; + return map.containsKey(value) ? value : Value.NULL; } @Override - public Value slice(long from, Long to) + public Value slice(final long from, final Long to) { throw new InternalExpressionException("Cannot slice a map value"); } @Override - public Value split(Value delimiter) { - throw new InternalExpressionException("Cannot split a map value"); + public Value split(final Value delimiter) + { + throw new InternalExpressionException("Cannot split a map value"); } @Override public double readDoubleNumber() { - return (double)map.size(); + return map.size(); } @Override - public Value get(Value v2) + public Value get(final Value v2) { return map.getOrDefault(v2, Value.NULL); } @Override - public boolean has(Value where) + public boolean has(final Value where) { return map.containsKey(where); } @Override - public boolean delete(Value where) + public boolean delete(final Value where) { - Value ret = map.remove(where); - return ret != null; + return map.remove(where) != null; } @Override - public boolean put(Value key, Value value) + public boolean put(final Value key, final Value value) { - Value ret = map.put(key, value); - return ret != null; + return map.put(key, value) != null; } @Override @@ -259,12 +249,15 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - CompoundTag tag = new CompoundTag() ; - map.forEach( (k, v) -> + final CompoundTag tag = new CompoundTag(); + map.forEach((k, v) -> { - if (!force && !(k instanceof StringValue)) throw new NBTSerializableValue.IncompatibleTypeException(k); + if (!force && !(k instanceof StringValue)) + { + throw new NBTSerializableValue.IncompatibleTypeException(k); + } tag.put(k.getString(), v.toTag(force)); }); return tag; @@ -273,10 +266,10 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa @Override public JsonElement toJson() { - JsonObject jsonMap = new JsonObject(); - List keys = new ArrayList<>(map.keySet()); + final JsonObject jsonMap = new JsonObject(); + final List keys = new ArrayList<>(map.keySet()); Collections.sort(keys); - keys.forEach( k -> jsonMap.add(k.getString(), map.get(k).toJson())); + keys.forEach(k -> jsonMap.add(k.getString(), map.get(k).toJson())); return jsonMap; } } diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 272f3fb1..32cce9dd 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -8,6 +8,7 @@ import carpet.script.exception.Throwables; import carpet.script.utils.EquipmentInventory; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -17,6 +18,7 @@ import java.util.Map; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; + import net.minecraft.commands.arguments.NbtPathArgument; import net.minecraft.commands.arguments.item.ItemInput; import net.minecraft.commands.arguments.item.ItemParser; @@ -59,9 +61,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa private Supplier nbtSupplier = null; private boolean owned = false; - private NBTSerializableValue() {} + private NBTSerializableValue() + { + } - public NBTSerializableValue(String nbtString) + public NBTSerializableValue(final String nbtString) { nbtSupplier = () -> { @@ -69,64 +73,70 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa { return (new TagParser(new StringReader(nbtString))).readValue(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { - throw new InternalExpressionException("Incorrect NBT data: "+nbtString); + throw new InternalExpressionException("Incorrect NBT data: " + nbtString); } }; owned = true; } - public NBTSerializableValue(Tag tag) + public NBTSerializableValue(final Tag tag) { nbtTag = tag; owned = true; } - public static Value of(Tag tag) + public static Value of(final Tag tag) { - if (tag == null) return Value.NULL; + if (tag == null) + { + return Value.NULL; + } return new NBTSerializableValue(tag); } - public NBTSerializableValue(Supplier tagSupplier) + public NBTSerializableValue(final Supplier tagSupplier) { nbtSupplier = tagSupplier; } - public static Value fromStack(ItemStack stack) + public static Value fromStack(final ItemStack stack) { if (stack.hasTag()) { - NBTSerializableValue value = new NBTSerializableValue(); + final NBTSerializableValue value = new NBTSerializableValue(); value.nbtSupplier = stack::getTag; return value; } return Value.NULL; } - public static String nameFromRegistryId(ResourceLocation id) + public static String nameFromRegistryId(final ResourceLocation id) { if (id == null) // should be Value.NULL + { return ""; - if (id.getNamespace().equals("minecraft")) - return id.getPath(); - return id.toString(); + } + return id.getNamespace().equals("minecraft") ? id.getPath() : id.toString(); } - public static NBTSerializableValue parseString(String nbtString, boolean fail) + public static NBTSerializableValue parseString(final String nbtString, final boolean fail) { - Tag tag; + final Tag tag; try { tag = (new TagParser(new StringReader(nbtString))).readValue(); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { - if (fail) throw new InternalExpressionException("Incorrect NBT tag: "+ nbtString); + if (fail) + { + throw new InternalExpressionException("Incorrect NBT tag: " + nbtString); + } return null; } - NBTSerializableValue value = new NBTSerializableValue(tag); + final NBTSerializableValue value = new NBTSerializableValue(tag); value.nbtString = null; return value; } @@ -136,7 +146,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa public Value clone() { // sets only nbttag, even if emtpy; - NBTSerializableValue copy = new NBTSerializableValue(nbtTag); + final NBTSerializableValue copy = new NBTSerializableValue(nbtTag); copy.nbtSupplier = this.nbtSupplier; copy.nbtString = this.nbtString; copy.owned = this.owned; @@ -146,59 +156,67 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa @Override public Value deepcopy() { - NBTSerializableValue copy = (NBTSerializableValue) clone(); + final NBTSerializableValue copy = (NBTSerializableValue) clone(); copy.owned = false; ensureOwnership(); return copy; } @Override - public Value fromConstant() { + public Value fromConstant() + { return deepcopy(); } // stolen from HopperBlockEntity, adjusted for threaded operation - public static Container getInventoryAt(ServerLevel world, BlockPos blockPos) + public static Container getInventoryAt(final ServerLevel world, final BlockPos blockPos) { Container inventory = null; - BlockState blockState = world.getBlockState(blockPos); - Block block = blockState.getBlock(); - if (block instanceof WorldlyContainerHolder) { - inventory = ((WorldlyContainerHolder)block).getContainer(blockState, world, blockPos); - } else if (blockState.hasBlockEntity()) { - BlockEntity blockEntity = BlockValue.getBlockEntity(world, blockPos); - if (blockEntity instanceof Container) { - inventory = (Container)blockEntity; - if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) { - inventory = ChestBlock.getContainer((ChestBlock)block, blockState, world, blockPos, true); + final BlockState blockState = world.getBlockState(blockPos); + final Block block = blockState.getBlock(); + if (block instanceof final WorldlyContainerHolder containerHolder) + { + inventory = containerHolder.getContainer(blockState, world, blockPos); + } + else if (blockState.hasBlockEntity()) + { + final BlockEntity blockEntity = BlockValue.getBlockEntity(world, blockPos); + if (blockEntity instanceof final Container inventoryHolder) + { + inventory = inventoryHolder; + if (inventory instanceof ChestBlockEntity && block instanceof final ChestBlock chestBlock) + { + inventory = ChestBlock.getContainer(chestBlock, blockState, world, blockPos, true); } } } - if (inventory == null) { - List list = world.getEntities( - (Entity)null, //TODO check this matches the correct method + if (inventory == null) + { + final List list = world.getEntities( + (Entity) null, //TODO check this matches the correct method new AABB( blockPos.getX() - 0.5D, blockPos.getY() - 0.5D, blockPos.getZ() - 0.5D, blockPos.getX() + 0.5D, blockPos.getY() + 0.5D, blockPos.getZ() + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR ); - if (!list.isEmpty()) { - inventory = (Container)list.get(world.random.nextInt(list.size())); + if (!list.isEmpty()) + { + inventory = (Container) list.get(world.random.nextInt(list.size())); } } return inventory; } - public static InventoryLocator locateInventory(CarpetContext c, List params, int offset) + public static InventoryLocator locateInventory(final CarpetContext c, final List params, int offset) { try { Value v1 = params.get(offset); if (v1.isNull()) { - offset ++; + offset++; v1 = params.get(offset); } else if (v1 instanceof StringValue) @@ -206,23 +224,38 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa String strVal = v1.getString().toLowerCase(Locale.ROOT); if (strVal.equals("enderchest")) { - Value v2 = params.get(1 + offset); - ServerPlayer player = EntityValue.getPlayerByValue(c.server(), v2); - if (player == null) throw new InternalExpressionException("enderchest inventory requires player argument"); + final Value v2 = params.get(1 + offset); + final ServerPlayer player = EntityValue.getPlayerByValue(c.server(), v2); + if (player == null) + { + throw new InternalExpressionException("enderchest inventory requires player argument"); + } return new InventoryLocator(player, player.blockPosition(), player.getEnderChestInventory(), offset + 2, true); } if (strVal.equals("equipment")) { - Value v2 = params.get(1 + offset); - if (!(v2 instanceof EntityValue)) throw new InternalExpressionException("Equipment inventory requires a living entity argument"); - Entity e = ((EntityValue) v2).getEntity(); - if (!(e instanceof LivingEntity)) throw new InternalExpressionException("Equipment inventory requires a living entity argument"); - return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory((LivingEntity) e), offset + 2); + final Value v2 = params.get(1 + offset); + if (!(v2 instanceof final EntityValue ev)) + { + throw new InternalExpressionException("Equipment inventory requires a living entity argument"); + } + final Entity e = ev.getEntity(); + if (!(e instanceof final LivingEntity le)) + { + throw new InternalExpressionException("Equipment inventory requires a living entity argument"); + } + return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory(le), offset + 2); + } + final boolean isEnder = strVal.startsWith("enderchest_"); + if (isEnder) + { + strVal = strVal.substring(11); // len("enderchest_") + } + final ServerPlayer player = c.server().getPlayerList().getPlayerByName(strVal); + if (player == null) + { + throw new InternalExpressionException("String description of an inventory should either denote a player or player's enderchest"); } - boolean isEnder = strVal.startsWith("enderchest_"); - if (isEnder) strVal = strVal.substring(11); // len("enderchest_") - ServerPlayer player = c.server().getPlayerList().getPlayerByName(strVal); - if (player == null) throw new InternalExpressionException("String description of an inventory should either denote a player or player's enderchest"); return new InventoryLocator( player, player.blockPosition(), @@ -231,149 +264,150 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa isEnder ); } - if (v1 instanceof EntityValue) + if (v1 instanceof final EntityValue ev) { Container inv = null; - Entity e = ((EntityValue) v1).getEntity(); - if (e instanceof Player pe) inv = pe.getInventory(); - else if (e instanceof Container) inv = (Container) e; - else if (e instanceof InventoryCarrier io) inv = io.getInventory(); - else if (e instanceof InventoryBearerInterface ibi) inv = ibi.getCMInventory(); // horse only - else if (e instanceof LivingEntity le) return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory(le), offset+1); - if (inv == null) - return null; + final Entity e = ev.getEntity(); + if (e instanceof final Player pe) + { + inv = pe.getInventory(); + } + else if (e instanceof final Container container) + { + inv = container; + } + else if (e instanceof final InventoryCarrier io) + { + inv = io.getInventory(); + } + else if (e instanceof final InventoryBearerInterface ibi) + { + inv = ibi.getCMInventory(); // horse only + } + else if (e instanceof final LivingEntity le) + { + return new InventoryLocator(e, e.blockPosition(), new EquipmentInventory(le), offset + 1); + } + return inv == null ? null : new InventoryLocator(e, e.blockPosition(), inv, offset + 1); - return new InventoryLocator(e, e.blockPosition(), inv, offset+1); } - if (v1 instanceof BlockValue) + if (v1 instanceof final BlockValue bv) { - BlockPos pos = ((BlockValue) v1).getPos(); + final BlockPos pos = bv.getPos(); if (pos == null) + { throw new InternalExpressionException("Block to access inventory needs to be positioned in the world"); - Container inv = getInventoryAt(c.level(), pos); - if (inv == null) - return null; - return new InventoryLocator(pos, pos, inv, offset+1); + } + final Container inv = getInventoryAt(c.level(), pos); + return inv == null ? null : new InventoryLocator(pos, pos, inv, offset + 1); } - if (v1 instanceof ListValue) + if (v1 instanceof final ListValue lv) { - List args = ((ListValue) v1).getItems(); - BlockPos pos = new BlockPos( + final List args = lv.getItems(); + final BlockPos pos = new BlockPos( NumericValue.asNumber(args.get(0)).getDouble(), NumericValue.asNumber(args.get(1)).getDouble(), NumericValue.asNumber(args.get(2)).getDouble()); - Container inv = getInventoryAt(c.level(), pos); - if (inv == null) - return null; - return new InventoryLocator(pos, pos, inv, offset+1); + final Container inv = getInventoryAt(c.level(), pos); + return inv == null ? null : new InventoryLocator(pos, pos, inv, offset + 1); } - if (v1 instanceof ScreenValue screenValue) + if (v1 instanceof final ScreenValue screenValue) { - if(!screenValue.isOpen()) return null; - return new InventoryLocator(screenValue.getPlayer(), screenValue.getPlayer().blockPosition(), screenValue.getInventory(), offset+1); + return !screenValue.isOpen() ? null : new InventoryLocator(screenValue.getPlayer(), screenValue.getPlayer().blockPosition(), screenValue.getInventory(), offset + 1); } - BlockPos pos = new BlockPos( + final BlockPos pos = new BlockPos( NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(params.get(1 + offset)).getDouble(), NumericValue.asNumber(params.get(2 + offset)).getDouble()); - Container inv = getInventoryAt(c.level(), pos); - if (inv == null) - return null; - return new InventoryLocator(pos, pos, inv, offset + 3); + final Container inv = getInventoryAt(c.level(), pos); + return inv == null ? null : new InventoryLocator(pos, pos, inv, offset + 3); } - catch (IndexOutOfBoundsException e) + catch (final IndexOutOfBoundsException e) { throw new InternalExpressionException("Inventory should be defined either by three coordinates, a block value, an entity, or a screen"); } } - private static final Map itemCache = new HashMap<>(); + private static final Map itemCache = new HashMap<>(); - public static ItemInput parseItem(String itemString, RegistryAccess regs) + public static ItemInput parseItem(final String itemString, final RegistryAccess regs) { return parseItem(itemString, null, regs); } - public static ItemInput parseItem(String itemString, CompoundTag customTag, RegistryAccess regs) + public static ItemInput parseItem(final String itemString, final CompoundTag customTag, final RegistryAccess regs) { try { ItemInput res = itemCache.get(itemString); // [SCARY SHIT] persistent caches over server reloads if (res != null) - if (customTag == null) - return res; - else - return new ItemInput(Holder.direct(res.getItem()), customTag); - ItemParser.ItemResult parser = ItemParser.parseForItem(regs.lookupOrThrow(Registries.ITEM), new StringReader(itemString)); + { + return customTag == null ? res : new ItemInput(Holder.direct(res.getItem()), customTag); + } + final ItemParser.ItemResult parser = ItemParser.parseForItem(regs.lookupOrThrow(Registries.ITEM), new StringReader(itemString)); res = new ItemInput(parser.item(), parser.nbt()); itemCache.put(itemString, res); - if (itemCache.size()>64000) + if (itemCache.size() > 64000) + { itemCache.clear(); - if (customTag == null) - return res; - else - return new ItemInput(Holder.direct(res.getItem()), customTag); + } + return customTag == null ? res : new ItemInput(Holder.direct(res.getItem()), customTag); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { throw new ThrowStatement(itemString, Throwables.UNKNOWN_ITEM); } } - public static int validateSlot(int slot, Container inv) + public static int validateSlot(int slot, final Container inv) { - int invSize = inv.getContainerSize(); + final int invSize = inv.getContainerSize(); if (slot < 0) + { slot = invSize + slot; - if (slot < 0 || slot >= invSize) - return inv.getContainerSize(); // outside of inventory - return slot; + } + return slot < 0 || slot >= invSize ? inv.getContainerSize() : slot; // outside of inventory } - private static Value decodeSimpleTag(Tag t) + private static Value decodeSimpleTag(final Tag t) { - if (t instanceof NumericTag) + if (t instanceof final NumericTag number) { - if (t instanceof LongTag || t instanceof IntTag) // short and byte will never exceed float's precision, even int won't - { - return NumericValue.of(((NumericTag) t).getAsLong()); - } - return NumericValue.of(((NumericTag) t).getAsNumber()); + // short and byte will never exceed float's precision, even int won't + return t instanceof LongTag || t instanceof IntTag ? NumericValue.of(number.getAsLong()) : NumericValue.of(number.getAsNumber()); } if (t instanceof StringTag) - return StringValue.of(t.getAsString()); - if (t instanceof EndTag) - return Value.NULL; - - throw new InternalExpressionException("How did we get here: Unknown nbt element class: "+t.getType().getName()); - - } - - private static Value decodeTag(Tag t) - { - if (t instanceof CompoundTag || t instanceof CollectionTag) - return new NBTSerializableValue(() -> t); - return decodeSimpleTag(t); - } - - private static Value decodeTagDeep(Tag t) - { - if (t instanceof CompoundTag) { - Map pairs = new HashMap<>(); - CompoundTag ctag = (CompoundTag)t; - for (String key: ctag.getAllKeys()) + return StringValue.of(t.getAsString()); + } + if (t instanceof EndTag) + { + return Value.NULL; + } + throw new InternalExpressionException("How did we get here: Unknown nbt element class: " + t.getType().getName()); + } + + private static Value decodeTag(final Tag t) + { + return t instanceof CompoundTag || t instanceof CollectionTag ? new NBTSerializableValue(() -> t) : decodeSimpleTag(t); + } + + private static Value decodeTagDeep(final Tag t) + { + if (t instanceof final CompoundTag ctag) + { + final Map pairs = new HashMap<>(); + for (final String key : ctag.getAllKeys()) { pairs.put(new StringValue(key), decodeTagDeep(ctag.get(key))); } return MapValue.wrap(pairs); } - if (t instanceof CollectionTag) + if (t instanceof final CollectionTag ltag) { - List elems = new ArrayList<>(); - CollectionTag ltag = (CollectionTag)t; - for (Tag elem: ltag) + final List elems = new ArrayList<>(); + for (final Tag elem : ltag) { elems.add(decodeTagDeep(elem)); } @@ -387,50 +421,64 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return decodeTagDeep(this.getTag()); } - public static Value fromValue(Value v) + public static Value fromValue(final Value v) { if (v instanceof NBTSerializableValue) + { return v; + } if (v.isNull()) + { return Value.NULL; + } return NBTSerializableValue.parseString(v.getString(), true); } public Tag getTag() { if (nbtTag == null) + { nbtTag = nbtSupplier.get(); + } return nbtTag; } @Override public boolean equals(final Object o) { - if (o instanceof NBTSerializableValue) - return getTag().equals(((NBTSerializableValue) o).getTag()); - return super.equals(o); + return o instanceof final NBTSerializableValue nbtsv ? getTag().equals(nbtsv.getTag()) : super.equals(o); } @Override public String getString() { if (nbtString == null) + { nbtString = getTag().toString(); + } return nbtString; } @Override public boolean getBoolean() { - Tag tag = getTag(); - if (tag instanceof CompoundTag) - return !((CompoundTag) tag).isEmpty(); - if (tag instanceof CollectionTag) - return !((CollectionTag) tag).isEmpty(); - if (tag instanceof NumericTag) - return ((NumericTag) tag).getAsDouble()!=0.0; + final Tag tag = getTag(); + if (tag instanceof final CompoundTag ctag) + { + return !(ctag).isEmpty(); + } + if (tag instanceof final CollectionTag ltag) + { + return !(ltag).isEmpty(); + } + if (tag instanceof final NumericTag number) + { + return number.getAsDouble() != 0.0; + } if (tag instanceof StringTag) + { return !tag.getAsString().isEmpty(); + } return true; } @@ -441,86 +489,89 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa ensureOwnership(); return (CompoundTag) getTag(); } - catch (ClassCastException e) + catch (final ClassCastException e) { - throw new InternalExpressionException(getString()+" is not a valid compound tag"); + throw new InternalExpressionException(getString() + " is not a valid compound tag"); } } @Override - public boolean put(Value where, Value value) + public boolean put(final Value where, final Value value) { return put(where, value, new StringValue("replace")); } @Override - public boolean put(Value where, Value value, Value conditions) + public boolean put(final Value where, final Value value, final Value conditions) { /// WIP ensureOwnership(); - NbtPathArgument.NbtPath path = cachePath(where.getString()); - Tag tagToInsert = value instanceof NBTSerializableValue ? - ((NBTSerializableValue) value).getTag() : - new NBTSerializableValue(value.getString()).getTag(); - boolean modifiedTag; - if (conditions instanceof NumericValue) + final NbtPathArgument.NbtPath path = cachePath(where.getString()); + final Tag tagToInsert = value instanceof final NBTSerializableValue nbtsv + ? nbtsv.getTag() + : new NBTSerializableValue(value.getString()).getTag(); + final boolean modifiedTag; + if (conditions instanceof final NumericValue number) { - modifiedTag = modify_insert((int)((NumericValue) conditions).getLong(), path, tagToInsert); + modifiedTag = modifyInsert((int) number.getLong(), path, tagToInsert); } else { - String ops = conditions.getString(); + final String ops = conditions.getString(); if (ops.equalsIgnoreCase("merge")) { - modifiedTag = modify_merge(path, tagToInsert); + modifiedTag = modifyMerge(path, tagToInsert); } else if (ops.equalsIgnoreCase("replace")) { - modifiedTag = modify_replace(path, tagToInsert); + modifiedTag = modifyReplace(path, tagToInsert); } else { return false; } } - if (modifiedTag) dirty(); + if (modifiedTag) + { + dirty(); + } return modifiedTag; } - - private boolean modify_insert(int index, NbtPathArgument.NbtPath nbtPath, Tag newElement) + private boolean modifyInsert(final int index, final NbtPathArgument.NbtPath nbtPath, final Tag newElement) { - return modify_insert(index, nbtPath, newElement, this.getTag()); + return modifyInsert(index, nbtPath, newElement, this.getTag()); } - private boolean modify_insert(int index, NbtPathArgument.NbtPath nbtPath, Tag newElement, Tag currentTag) + private boolean modifyInsert(final int index, final NbtPathArgument.NbtPath nbtPath, final Tag newElement, final Tag currentTag) { - Collection targets; + final Collection targets; try { targets = nbtPath.getOrCreate(currentTag, ListTag::new); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { return false; } boolean modified = false; - for (Tag target : targets) + for (final Tag target : targets) { - if (!(target instanceof CollectionTag)) + if (!(target instanceof final CollectionTag targetList)) { continue; } try { - CollectionTag targetList = (CollectionTag) target; if (!targetList.addTag(index < 0 ? targetList.size() + index + 1 : index, newElement.copy())) + { return false; + } modified = true; } - catch (IndexOutOfBoundsException ignored) + catch (final IndexOutOfBoundsException ignored) { } } @@ -528,68 +579,72 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } - private boolean modify_merge(NbtPathArgument.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) + private boolean modifyMerge(final NbtPathArgument.NbtPath nbtPath, final Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) { - if (!(replacement instanceof CompoundTag)) + if (!(replacement instanceof final CompoundTag replacementCompound)) { return false; } - Tag ownTag = getTag(); + final Tag ownTag = getTag(); try { - for (Tag target : nbtPath.getOrCreate(ownTag, CompoundTag::new)) + for (final Tag target : nbtPath.getOrCreate(ownTag, CompoundTag::new)) { - if (!(target instanceof CompoundTag)) + if (!(target instanceof final CompoundTag targetCompound)) { continue; } - ((CompoundTag) target).merge((CompoundTag) replacement); + targetCompound.merge(replacementCompound); } } - catch (CommandSyntaxException ignored) + catch (final CommandSyntaxException ignored) { return false; } return true; } - private boolean modify_replace(NbtPathArgument.NbtPath nbtPath, Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) + private boolean modifyReplace(final NbtPathArgument.NbtPath nbtPath, final Tag replacement) //nbtPathArgumentType$NbtPath_1, list_1) { - Tag tag = getTag(); - String pathText = nbtPath.toString(); + final Tag tag = getTag(); + final String pathText = nbtPath.toString(); if (pathText.endsWith("]")) // workaround for array replacement or item in the array replacement { - if (nbtPath.remove(tag)==0) + if (nbtPath.remove(tag) == 0) + { return false; - Pattern pattern = Pattern.compile("\\[[^\\[]*]$"); - Matcher matcher = pattern.matcher(pathText); + } + final Pattern pattern = Pattern.compile("\\[[^\\[]*]$"); + final Matcher matcher = pattern.matcher(pathText); if (!matcher.find()) // malformed path { return false; } - String arrAccess = matcher.group(); - int pos; - if (arrAccess.length()==2) // we just removed entire array + final String arrAccess = matcher.group(); + final int pos; + if (arrAccess.length() == 2) // we just removed entire array + { pos = 0; + } else { try { pos = Integer.parseInt(arrAccess.substring(1, arrAccess.length() - 1)); } - catch (NumberFormatException e) + catch (final NumberFormatException e) { return false; } } - NbtPathArgument.NbtPath newPath = cachePath(pathText.substring(0, pathText.length()-arrAccess.length())); - return modify_insert(pos,newPath,replacement, tag); + final NbtPathArgument.NbtPath newPath = cachePath(pathText.substring(0, pathText.length() - arrAccess.length())); + return modifyInsert(pos, newPath, replacement, tag); } try { nbtPath.set(tag, replacement); } - catch (CommandSyntaxException e) + catch (final CommandSyntaxException e) { return false; } @@ -597,25 +652,31 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } @Override - public Value get(Value value) + public Value get(final Value value) { - String valString = value.getString(); - NbtPathArgument.NbtPath path = cachePath(valString); + final String valString = value.getString(); + final NbtPathArgument.NbtPath path = cachePath(valString); try { - List tags = path.get(getTag()); - if (tags.size()==0) + final List tags = path.get(getTag()); + if (tags.isEmpty()) + { return Value.NULL; - if (tags.size()==1 && !valString.endsWith("[]")) + } + if (tags.size() == 1 && !valString.endsWith("[]")) + { return NBTSerializableValue.decodeTag(tags.get(0)); + } return ListValue.wrap(tags.stream().map(NBTSerializableValue::decodeTag)); } - catch (CommandSyntaxException ignored) { } + catch (final CommandSyntaxException ignored) + { + } return Value.NULL; } @Override - public boolean has(Value where) + public boolean has(final Value where) { return cachePath(where.getString()).countMatching(getTag()) > 0; } @@ -637,11 +698,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } @Override - public boolean delete(Value where) + public boolean delete(final Value where) { - NbtPathArgument.NbtPath path = cachePath(where.getString()); + final NbtPathArgument.NbtPath path = cachePath(where.getString()); ensureOwnership(); - int removed = path.remove(getTag()); + final int removed = path.remove(getTag()); if (removed > 0) { dirty(); @@ -650,30 +711,36 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return false; } - public static record InventoryLocator(Object owner, BlockPos position, Container inventory, int offset, boolean isEnder) + public record InventoryLocator(Object owner, BlockPos position, Container inventory, int offset, + boolean isEnder) { - InventoryLocator(Object owner, BlockPos pos, Container i, int o) + InventoryLocator(final Object owner, final BlockPos pos, final Container i, final int o) { this(owner, pos, i, o, false); } } - private static Map pathCache = new HashMap<>(); - private static NbtPathArgument.NbtPath cachePath(String arg) + private static final Map pathCache = new HashMap<>(); + + private static NbtPathArgument.NbtPath cachePath(final String arg) { NbtPathArgument.NbtPath res = pathCache.get(arg); if (res != null) + { return res; + } try { res = NbtPathArgument.nbtPath().parse(new StringReader(arg)); } - catch (CommandSyntaxException exc) + catch (final CommandSyntaxException exc) { - throw new InternalExpressionException("Incorrect nbt path: "+arg); + throw new InternalExpressionException("Incorrect nbt path: " + arg); } if (pathCache.size() > 1024) + { pathCache.clear(); + } pathCache.put(arg, res); return res; } @@ -686,9 +753,12 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } ensureOwnership(); return getTag(); } @@ -696,9 +766,11 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa public static class IncompatibleTypeException extends RuntimeException { public final Value val; - public IncompatibleTypeException(Value val) + + public IncompatibleTypeException(final Value val) { this.val = val; } - }; + } + } diff --git a/src/main/java/carpet/script/value/NullValue.java b/src/main/java/carpet/script/value/NullValue.java index 9d68f02e..426a0f18 100644 --- a/src/main/java/carpet/script/value/NullValue.java +++ b/src/main/java/carpet/script/value/NullValue.java @@ -1,6 +1,7 @@ package carpet.script.value; import java.util.ArrayList; + import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import com.google.gson.JsonElement; @@ -9,6 +10,7 @@ import com.google.gson.JsonNull; public class NullValue extends NumericValue // TODO check nonsingleton code { public static final NullValue NULL = new NullValue(); + @Override public String getString() { @@ -32,41 +34,45 @@ public class NullValue extends NumericValue // TODO check nonsingleton code { return new NullValue(); } - protected NullValue() {super(0);} + + protected NullValue() + { + super(0); + } @Override public boolean equals(final Object o) { - if (o instanceof Value value) - { - return value.isNull(); - } - return false; + return o instanceof Value value && value.isNull(); } @Override - public Value slice(long fromDesc, Long toDesc) { + public Value slice(final long fromDesc, final Long toDesc) + { return Value.NULL; } @Override - public NumericValue opposite() { + public NumericValue opposite() + { return Value.NULL; } @Override - public int length() { + public int length() + { return 0; } @Override - public int compareTo(Value o) + public int compareTo(final Value o) { - return o.isNull() ? 0 : -1; + return o.isNull() ? 0 : -1; } @Override - public Value in(Value value) { + public Value in(final Value value) + { return Value.NULL; } @@ -83,15 +89,19 @@ public class NullValue extends NumericValue // TODO check nonsingleton code } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } return StringTag.valueOf("null"); } @Override - public Value split(Value delimiter) { - return ListValue.wrap(new ArrayList()); + public Value split(final Value delimiter) + { + return ListValue.wrap(new ArrayList<>()); } @Override @@ -101,7 +111,8 @@ public class NullValue extends NumericValue // TODO check nonsingleton code } @Override - public boolean isNull() { + public boolean isNull() + { return true; } } diff --git a/src/main/java/carpet/script/value/NumericValue.java b/src/main/java/carpet/script/value/NumericValue.java index 2c4635e1..9a1a1b59 100644 --- a/src/main/java/carpet/script/value/NumericValue.java +++ b/src/main/java/carpet/script/value/NumericValue.java @@ -9,6 +9,7 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.Locale; + import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.IntTag; import net.minecraft.nbt.LongTag; @@ -21,28 +22,41 @@ public class NumericValue extends Value { private final double value; private Long longValue; - private final static double epsilon = abs(32*((7*0.1)*10-7)); - private final static MathContext displayRounding = new MathContext(12, RoundingMode.HALF_EVEN); + private static final double epsilon = abs(32 * ((7 * 0.1) * 10 - 7)); + private static final MathContext displayRounding = new MathContext(12, RoundingMode.HALF_EVEN); - public static NumericValue asNumber(Value v1, String id) + public static NumericValue asNumber(final Value v1, final String id) { - if (!(v1 instanceof NumericValue)) - throw new InternalExpressionException("Argument "+id+" has to be of a numeric type"); - return ((NumericValue) v1); + if (v1 instanceof final NumericValue nv) + { + return nv; + } + throw new InternalExpressionException("Argument " + id + " has to be of a numeric type"); } - public static NumericValue asNumber(Value v1) + public static NumericValue asNumber(final Value v1) { - if (!(v1 instanceof NumericValue)) - throw new InternalExpressionException("Operand has to be of a numeric type"); - return ((NumericValue) v1); + if (v1 instanceof final NumericValue nv) + { + return nv; + } + throw new InternalExpressionException("Operand has to be of a numeric type"); } - public static Value of(T value) + public static Value of(final T value) { - if (value == null) return Value.NULL; - if (value.doubleValue() == value.longValue()) return new NumericValue(value.longValue()); - if (value instanceof Float) return new NumericValue(0.000_001D * Math.round(1_000_000.0D*value.doubleValue())); + if (value == null) + { + return Value.NULL; + } + if (value.doubleValue() == value.longValue()) + { + return new NumericValue(value.longValue()); + } + if (value instanceof Float) + { + return new NumericValue(0.000_001D * Math.round(1_000_000.0D * value.doubleValue())); + } return new NumericValue(value.doubleValue()); } @@ -56,30 +70,33 @@ public class NumericValue extends Value } try { - if (Double.isInfinite(value)) return (value>0)?"INFINITY":"-INFINITY"; - if (Double.isNaN(value)) return "NaN"; - if (abs(value) < epsilon) return (signum(value) < 0)?"-0":"0"; //zero rounding fails with big decimals + if (Double.isInfinite(value)) + { + return (value > 0) ? "INFINITY" : "-INFINITY"; + } + if (Double.isNaN(value)) + { + return "NaN"; + } + if (abs(value) < epsilon) + { + return (signum(value) < 0) ? "-0" : "0"; //zero rounding fails with big decimals + } // dobules have 16 point precision, 12 is plenty to display return BigDecimal.valueOf(value).round(displayRounding).stripTrailingZeros().toPlainString(); } - catch (NumberFormatException exc) + catch (final NumberFormatException exc) { - throw new InternalExpressionException("Incorrect number format for "+value); + throw new InternalExpressionException("Incorrect number format for " + value); } } @Override public String getPrettyString() { - - if (longValue!= null || getDouble() == (double)getLong()) - { - return Long.toString(getLong()); - } - else - { - return String.format(Locale.ROOT, "%.1f..", getDouble()); - } + return longValue != null || getDouble() == getLong() + ? Long.toString(getLong()) + : String.format(Locale.ROOT, "%.1f..", getDouble()); } @Override @@ -87,80 +104,62 @@ public class NumericValue extends Value { return abs(value) > epsilon; } + public double getDouble() { return value; } + public float getFloat() { return (float) value; } - private static long floor(double double_1) { - long int_1 = (long)double_1; - return double_1 < (double)int_1 ? int_1 - 1 : int_1; + private static long floor(final double v) + { + final long invValue = (long) v; + return v < invValue ? invValue - 1 : invValue; } public long getLong() { - if (longValue != null) return longValue; - return floor((value+epsilon)); + return longValue != null ? longValue : Long.valueOf(floor((value + epsilon))); } @Override - public Value add(Value v) + public Value add(final Value v) { // TODO test if definintn add(NumericVlaue) woud solve the casting - if (v instanceof NumericValue nv) + if (v instanceof final NumericValue nv) { - if (longValue != null && nv.longValue != null) - { - return new NumericValue(longValue+nv.longValue); - } - return new NumericValue(value + nv.value); + return new NumericValue(longValue != null && nv.longValue != null ? (longValue + nv.longValue) : (value + nv.value)); } return super.add(v); } @Override - public Value subtract(Value v) { // TODO test if definintn add(NumericVlaue) woud solve the casting - if (v instanceof NumericValue nv) + public Value subtract(final Value v) + { // TODO test if definintn add(NumericVlaue) woud solve the casting + if (v instanceof final NumericValue nv) { - if (longValue != null && nv.longValue != null) - { - return new NumericValue(longValue-nv.longValue); - } - return new NumericValue(value - nv.value); + return new NumericValue(longValue != null && nv.longValue != null ? (longValue - nv.longValue) : (value - nv.value)); } return super.subtract(v); } @Override - public Value multiply(Value v) + public Value multiply(final Value v) { - if (v instanceof NumericValue nv) + if (v instanceof final NumericValue nv) { - if (longValue != null && nv.longValue != null) - { - return new NumericValue(longValue*nv.longValue); - } - return new NumericValue(value * nv.value); + return new NumericValue(longValue != null && nv.longValue != null ? (longValue * nv.longValue) : (value * nv.value)); } - if (v instanceof ListValue) - { - return v.multiply(this); - } - return new StringValue(StringUtils.repeat(v.getString(), (int) getLong())); + return v instanceof ListValue ? v.multiply(this) : new StringValue(StringUtils.repeat(v.getString(), (int) getLong())); } @Override - public Value divide(Value v) + public Value divide(final Value v) { - //if (1+2==3) throw new ArithmeticException("Booyah"); - if (v instanceof NumericValue) - { - return new NumericValue(getDouble() / ((NumericValue) v).getDouble() ); - } - return super.divide(v); + return v instanceof final NumericValue nv ? new NumericValue(getDouble() / nv.getDouble()) : super.divide(v); } @Override @@ -170,64 +169,68 @@ public class NumericValue extends Value } @Override - public int compareTo(Value o) + public int compareTo(final Value o) { if (o.isNull()) { return -o.compareTo(this); } - if (o instanceof NumericValue no) + if (o instanceof final NumericValue no) { - if (longValue != null && no.longValue != null) - return longValue.compareTo(no.longValue); - return Double.compare(value, no.value); + return longValue != null && no.longValue != null ? longValue.compareTo(no.longValue) : Double.compare(value, no.value); } return getString().compareTo(o.getString()); } + @Override - public boolean equals(Object o) + public boolean equals(final Object o) { - if (o instanceof Value value) { - if (value.isNull()) { + if (o instanceof final Value otherValue) + { + if (otherValue.isNull()) + { return o.equals(this); } - if (o instanceof NumericValue no) { - if (longValue != null && no.longValue != null) - return longValue.equals(no.longValue); - return !this.subtract(no).getBoolean(); + if (o instanceof final NumericValue no) + { + return longValue != null && no.longValue != null ? longValue.equals(no.longValue) : !this.subtract(no).getBoolean(); } return super.equals(o); } return false; } - public NumericValue(double value) + public NumericValue(final double value) { this.value = value; } - private NumericValue(double value, Long longValue) + + private NumericValue(final double value, final Long longValue) { this.value = value; this.longValue = longValue; } - public NumericValue(String value) + public NumericValue(final String value) { - BigDecimal decimal = new BigDecimal(value); + final BigDecimal decimal = new BigDecimal(value); if (decimal.stripTrailingZeros().scale() <= 0) { try { longValue = decimal.longValueExact(); } - catch (ArithmeticException ignored) {} + catch (final ArithmeticException ignored) + { + } } this.value = decimal.doubleValue(); } - public NumericValue(long value) + + public NumericValue(final long value) { this.longValue = value; - this.value = (double)value; + this.value = (double) value; } @Override @@ -257,31 +260,34 @@ public class NumericValue extends Value @Override public int hashCode() { - if (longValue!= null || Math.abs(Math.floor(value + 0.5D)-value) < epsilon) // is sufficiently close to the integer value - return Long.hashCode(getLong()); - return Double.hashCode(value); + // is sufficiently close to the integer value + return longValue != null || Math.abs(Math.floor(value + 0.5D) - value) < epsilon ? Long.hashCode(getLong()) : Double.hashCode(value); } public int getInt() { - return (int)getLong(); + return (int) getLong(); } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { if (longValue != null) { - if (abs(longValue) < Integer.MAX_VALUE-2) - return IntTag.valueOf((int)(long)longValue); + if (abs(longValue) < Integer.MAX_VALUE - 2) + { + return IntTag.valueOf((int) (long) longValue); + } return LongTag.valueOf(longValue); } - long lv = getLong(); - if (value == (double)lv) + final long lv = getLong(); + if (value == (double) lv) { - if (abs(value) < Integer.MAX_VALUE-2) - return IntTag.valueOf((int)lv); + if (abs(value) < Integer.MAX_VALUE - 2) + { + return IntTag.valueOf((int) lv); + } return LongTag.valueOf(getLong()); } else @@ -294,35 +300,35 @@ public class NumericValue extends Value public JsonElement toJson() { if (longValue != null) + { return new JsonPrimitive(longValue); - long lv = getLong(); - if (value == (double)lv) - { - return new JsonPrimitive(getLong()); - } - else - { - return new JsonPrimitive(value); } + final long lv = getLong(); + return new JsonPrimitive(value == lv ? getLong() : value); } - public NumericValue opposite() { - if (longValue != null) return new NumericValue(-longValue); - return new NumericValue(-value); + public NumericValue opposite() + { + return new NumericValue(longValue != null ? -longValue : -value); } public boolean isInteger() { - return longValue!= null || getDouble() == (double)getLong(); + return longValue != null || getDouble() == getLong(); } - public Value mod(NumericValue n2) + public Value mod(final NumericValue n2) { if (this.longValue != null && n2.longValue != null) + { return new NumericValue(Math.floorMod(longValue, n2.longValue)); - double x = value; - double y = n2.value; - if (y == 0) throw new ArithmeticException("Division by zero"); - return new NumericValue( x - Math.floor(x / y) * y); + } + final double x = value; + final double y = n2.value; + if (y == 0) + { + throw new ArithmeticException("Division by zero"); + } + return new NumericValue(x - Math.floor(x / y) * y); } } diff --git a/src/main/java/carpet/script/value/ScreenValue.java b/src/main/java/carpet/script/value/ScreenValue.java index 8ab0ab78..0c144c52 100644 --- a/src/main/java/carpet/script/value/ScreenValue.java +++ b/src/main/java/carpet/script/value/ScreenValue.java @@ -12,11 +12,13 @@ import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InvalidCallbackException; import carpet.script.exception.ThrowStatement; import carpet.script.exception.Throwables; + import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.OptionalInt; + import net.minecraft.commands.CommandSourceStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -29,37 +31,14 @@ import net.minecraft.world.SimpleContainer; import net.minecraft.world.SimpleMenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.AbstractFurnaceMenu; -import net.minecraft.world.inventory.AnvilMenu; -import net.minecraft.world.inventory.BeaconMenu; -import net.minecraft.world.inventory.BlastFurnaceMenu; -import net.minecraft.world.inventory.BrewingStandMenu; -import net.minecraft.world.inventory.CartographyTableMenu; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ClickType; -import net.minecraft.world.inventory.ContainerListener; -import net.minecraft.world.inventory.CraftingMenu; -import net.minecraft.world.inventory.DataSlot; -import net.minecraft.world.inventory.EnchantmentMenu; -import net.minecraft.world.inventory.FurnaceMenu; -import net.minecraft.world.inventory.GrindstoneMenu; -import net.minecraft.world.inventory.HopperMenu; -import net.minecraft.world.inventory.LecternMenu; -import net.minecraft.world.inventory.LoomMenu; -import net.minecraft.world.inventory.MerchantMenu; -import net.minecraft.world.inventory.ShulkerBoxMenu; -import net.minecraft.world.inventory.SimpleContainerData; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.inventory.SmithingMenu; -import net.minecraft.world.inventory.SmokerMenu; -import net.minecraft.world.inventory.StonecutterMenu; +import net.minecraft.world.inventory.*; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import static net.minecraft.world.inventory.MenuType.*; -public class ScreenValue extends Value { +public class ScreenValue extends Value +{ private AbstractContainerMenu screenHandler; private ScreenHandlerInventory inventory; @@ -69,83 +48,96 @@ public class ScreenValue extends Value { private final String hostname; private final ServerPlayer player; - - public static Map screenHandlerFactories; + public static Map screenHandlerFactories; static { screenHandlerFactories = new HashMap<>(); - - screenHandlerFactories.put("anvil",(syncId, playerInventory) -> new AnvilMenu(syncId,playerInventory)); - screenHandlerFactories.put("beacon",(syncId, playerInventory) -> new BeaconMenu(syncId,playerInventory)); - screenHandlerFactories.put("blast_furnace",(syncId, playerInventory) -> new BlastFurnaceMenu(syncId,playerInventory)); - screenHandlerFactories.put("brewing_stand",(syncId, playerInventory) -> new BrewingStandMenu(syncId,playerInventory,new SimpleContainer(5),new SimpleContainerData(2))); - screenHandlerFactories.put("cartography_table",(syncId, playerInventory) -> new CartographyTableMenu(syncId,playerInventory)); - screenHandlerFactories.put("crafting",(syncId, playerInventory) -> new CraftingMenu(syncId,playerInventory)); - screenHandlerFactories.put("enchantment",(syncId, playerInventory) -> new EnchantmentMenu(syncId,playerInventory)); - screenHandlerFactories.put("furnace",(syncId, playerInventory) -> new FurnaceMenu(syncId,playerInventory)); - screenHandlerFactories.put("generic_3x3",((syncId, playerInventory) -> new ChestMenu(GENERIC_3x3,syncId,playerInventory,new SimpleContainer(9),1))); - screenHandlerFactories.put("generic_9x1",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x1,syncId,playerInventory,new SimpleContainer(9),1))); - screenHandlerFactories.put("generic_9x2",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x2,syncId,playerInventory,new SimpleContainer(9*2),2))); - screenHandlerFactories.put("generic_9x3",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x3,syncId,playerInventory,new SimpleContainer(9*3),3))); - screenHandlerFactories.put("generic_9x4",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x4,syncId,playerInventory,new SimpleContainer(9*4),4))); - screenHandlerFactories.put("generic_9x5",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x5,syncId,playerInventory,new SimpleContainer(9*5),5))); - screenHandlerFactories.put("generic_9x6",((syncId, playerInventory) -> new ChestMenu(GENERIC_9x6,syncId,playerInventory,new SimpleContainer(9*6),6))); - screenHandlerFactories.put("grindstone",(syncId, playerInventory) -> new GrindstoneMenu(syncId,playerInventory)); - screenHandlerFactories.put("hopper",(syncId, playerInventory) -> new HopperMenu(syncId,playerInventory)); - screenHandlerFactories.put("lectern",(syncId, playerInventory) -> new LecternMenu(syncId,new SimpleContainer(1),new SimpleContainerData(1))); - screenHandlerFactories.put("loom",(syncId, playerInventory) -> new LoomMenu(syncId,playerInventory)); - screenHandlerFactories.put("merchant",(syncId, playerInventory) -> new MerchantMenu(syncId,playerInventory)); - screenHandlerFactories.put("shulker_box",(syncId, playerInventory) -> new ShulkerBoxMenu(syncId,playerInventory,new SimpleContainer(9*3))); - screenHandlerFactories.put("smithing",(syncId, playerInventory) -> new SmithingMenu(syncId,playerInventory)); - screenHandlerFactories.put("smoker",(syncId, playerInventory) -> new SmokerMenu(syncId,playerInventory)); - screenHandlerFactories.put("stonecutter",(syncId, playerInventory) -> new StonecutterMenu(syncId,playerInventory)); + screenHandlerFactories.put("anvil", AnvilMenu::new); + screenHandlerFactories.put("beacon", BeaconMenu::new); + screenHandlerFactories.put("blast_furnace", BlastFurnaceMenu::new); + screenHandlerFactories.put("brewing_stand", (syncId, playerInventory) -> new BrewingStandMenu(syncId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2))); + screenHandlerFactories.put("cartography_table", CartographyTableMenu::new); + screenHandlerFactories.put("crafting", CraftingMenu::new); + screenHandlerFactories.put("enchantment", EnchantmentMenu::new); + screenHandlerFactories.put("furnace", FurnaceMenu::new); + screenHandlerFactories.put("generic_3x3", ((syncId, playerInventory) -> new ChestMenu(GENERIC_3x3, syncId, playerInventory, new SimpleContainer(9), 1))); + screenHandlerFactories.put("generic_9x1", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x1, syncId, playerInventory, new SimpleContainer(9), 1))); + screenHandlerFactories.put("generic_9x2", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x2, syncId, playerInventory, new SimpleContainer(9 * 2), 2))); + screenHandlerFactories.put("generic_9x3", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x3, syncId, playerInventory, new SimpleContainer(9 * 3), 3))); + screenHandlerFactories.put("generic_9x4", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x4, syncId, playerInventory, new SimpleContainer(9 * 4), 4))); + screenHandlerFactories.put("generic_9x5", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x5, syncId, playerInventory, new SimpleContainer(9 * 5), 5))); + screenHandlerFactories.put("generic_9x6", ((syncId, playerInventory) -> new ChestMenu(GENERIC_9x6, syncId, playerInventory, new SimpleContainer(9 * 6), 6))); + screenHandlerFactories.put("grindstone", GrindstoneMenu::new); + screenHandlerFactories.put("hopper", HopperMenu::new); + screenHandlerFactories.put("lectern", (syncId, playerInventory) -> new LecternMenu(syncId, new SimpleContainer(1), new SimpleContainerData(1))); + screenHandlerFactories.put("loom", LoomMenu::new); + screenHandlerFactories.put("merchant", MerchantMenu::new); + screenHandlerFactories.put("shulker_box", (syncId, playerInventory) -> new ShulkerBoxMenu(syncId, playerInventory, new SimpleContainer(9 * 3))); + screenHandlerFactories.put("smithing_legacy", LegacySmithingMenu::new); + screenHandlerFactories.put("smithing", SmithingMenu::new); + screenHandlerFactories.put("smoker", SmokerMenu::new); + screenHandlerFactories.put("stonecutter", StonecutterMenu::new); } - protected interface ScarpetScreenHandlerFactory { + protected interface ScarpetScreenHandlerFactory + { AbstractContainerMenu create(int syncId, Inventory playerInventory); } - - - - public ScreenValue(ServerPlayer player, String type, Component name, FunctionValue callback, Context c) { + public ScreenValue(final ServerPlayer player, final String type, final Component name, final FunctionValue callback, final Context c) + { this.name = name; this.typestring = type.toLowerCase(); - if(callback != null) callback.checkArgs(4); + if (callback != null) + { + callback.checkArgs(4); + } this.callback = callback; this.hostname = c.host.getName(); this.player = player; - MenuProvider factory = this.createScreenHandlerFactory(); - if(factory == null) throw new ThrowStatement(type, Throwables.UNKNOWN_SCREEN); + final MenuProvider factory = this.createScreenHandlerFactory(); + if (factory == null) + { + throw new ThrowStatement(type, Throwables.UNKNOWN_SCREEN); + } this.openScreen(factory); this.inventory = new ScreenHandlerInventory(this.screenHandler); } - private MenuProvider createScreenHandlerFactory() { - if(!screenHandlerFactories.containsKey(this.typestring)) { + private MenuProvider createScreenHandlerFactory() + { + if (!screenHandlerFactories.containsKey(this.typestring)) + { return null; } return new SimpleMenuProvider((i, playerInventory, playerEntity) -> { - AbstractContainerMenu screen = screenHandlerFactories.get(ScreenValue.this.typestring).create(i,playerInventory); + final AbstractContainerMenu screen = screenHandlerFactories.get(ScreenValue.this.typestring).create(i, playerInventory); ScreenValue.this.addListenerCallback(screen); ScreenValue.this.screenHandler = screen; return screen; }, this.name); } - private void openScreen(MenuProvider factory) { - if(this.player == null) return; - OptionalInt optionalSyncId = this.player.openMenu(factory); - if(optionalSyncId.isPresent() && this.player.containerMenu.containerId == optionalSyncId.getAsInt()) { + private void openScreen(final MenuProvider factory) + { + if (this.player == null) + { + return; + } + final OptionalInt optionalSyncId = this.player.openMenu(factory); + if (optionalSyncId.isPresent() && this.player.containerMenu.containerId == optionalSyncId.getAsInt()) + { this.screenHandler = this.player.containerMenu; } } - public void close() { - if(this.player.containerMenu != this.player.inventoryMenu) { + public void close() + { + if (this.player.containerMenu != this.player.inventoryMenu) + { //prevent recursion when closing screen in closing screen callback by doing this before triggering event this.inventory = null; this.player.containerMenu = this.player.inventoryMenu; @@ -154,11 +146,14 @@ public class ScreenValue extends Value { } } - public boolean isOpen() { - if(this.screenHandler == null) { + public boolean isOpen() + { + if (this.screenHandler == null) + { return false; } - if(this.player.containerMenu.containerId == this.screenHandler.containerId) { + if (this.player.containerMenu.containerId == this.screenHandler.containerId) + { return true; } this.screenHandler = null; @@ -166,104 +161,124 @@ public class ScreenValue extends Value { } - private boolean callListener(ServerPlayer player, String action, Map data) { - Value playerValue = EntityValue.of(player); - Value actionValue = StringValue.of(action); - Value dataValue = MapValue.wrap(data); - List args = Arrays.asList(this,playerValue,actionValue,dataValue); - CarpetScriptHost appHost = CarpetServer.scriptServer.getAppHostByName(this.hostname); - if(appHost == null) { + private boolean callListener(final ServerPlayer player, final String action, final Map data) + { + final Value playerValue = EntityValue.of(player); + final Value actionValue = StringValue.of(action); + final Value dataValue = MapValue.wrap(data); + final List args = Arrays.asList(this, playerValue, actionValue, dataValue); + final CarpetScriptHost appHost = CarpetServer.scriptServer.getAppHostByName(this.hostname); + if (appHost == null) + { this.close(); this.screenHandler = null; return false; } - CommandSourceStack source = player.createCommandSourceStack().withPermission(CarpetSettings.runPermissionLevel); - CarpetScriptHost executingHost = appHost.retrieveForExecution(source,player); + final CommandSourceStack source = player.createCommandSourceStack().withPermission(CarpetSettings.runPermissionLevel); + final CarpetScriptHost executingHost = appHost.retrieveForExecution(source, player); try { - Value cancelValue = executingHost.callUDF(source.withPermission(CarpetSettings.runPermissionLevel), callback, args); + final Value cancelValue = executingHost.callUDF(source.withPermission(CarpetSettings.runPermissionLevel), callback, args); return cancelValue.getString().equals("cancel"); } - catch (NullPointerException | InvalidCallbackException | IntegrityException error) + catch (final NullPointerException | InvalidCallbackException | IntegrityException error) { CarpetScriptServer.LOG.error("Got exception when running screen event call ", error); return false; } } - private void addListenerCallback(AbstractContainerMenu screenHandler) { - if(this.callback == null) return; + private void addListenerCallback(final AbstractContainerMenu screenHandler) + { + if (this.callback == null) + { + return; + } - screenHandler.addSlotListener(new ScarpetScreenHandlerListener() { + screenHandler.addSlotListener(new ScarpetScreenHandlerListener() + { @Override - public boolean onSlotClick(ServerPlayer player, ClickType actionType, int slot, int button) { - Map data = new HashMap<>(); - data.put(StringValue.of("slot"),slot == AbstractContainerMenu.SLOT_CLICKED_OUTSIDE ? Value.NULL : NumericValue.of(slot)); - if(actionType == ClickType.QUICK_CRAFT) { - data.put(StringValue.of("quick_craft_stage"),NumericValue.of(AbstractContainerMenu.getQuickcraftHeader(button))); + public boolean onSlotClick(final ServerPlayer player, final ClickType actionType, final int slot, int button) + { + final Map data = new HashMap<>(); + data.put(StringValue.of("slot"), slot == AbstractContainerMenu.SLOT_CLICKED_OUTSIDE ? Value.NULL : NumericValue.of(slot)); + if (actionType == ClickType.QUICK_CRAFT) + { + data.put(StringValue.of("quick_craft_stage"), NumericValue.of(AbstractContainerMenu.getQuickcraftHeader(button))); button = AbstractContainerMenu.getQuickcraftType(button); } - data.put(StringValue.of("button"),NumericValue.of(button)); - return ScreenValue.this.callListener(player,actionTypeToString(actionType),data); + data.put(StringValue.of("button"), NumericValue.of(button)); + return ScreenValue.this.callListener(player, actionTypeToString(actionType), data); } + @Override - public boolean onButtonClick(ServerPlayer player, int button) { - Map data = new HashMap<>(); - data.put(StringValue.of("button"),NumericValue.of(button)); - return ScreenValue.this.callListener(player,"button",data); + public boolean onButtonClick(final ServerPlayer player, final int button) + { + final Map data = new HashMap<>(); + data.put(StringValue.of("button"), NumericValue.of(button)); + return ScreenValue.this.callListener(player, "button", data); } + @Override - public void onClose(ServerPlayer player) { - Map data = new HashMap<>(); - ScreenValue.this.callListener(player,"close",data); + public void onClose(final ServerPlayer player) + { + final Map data = new HashMap<>(); + ScreenValue.this.callListener(player, "close", data); } + @Override - public boolean onSelectRecipe(ServerPlayer player, Recipe recipe, boolean craftAll) { - Map data = new HashMap<>(); - data.put(StringValue.of("recipe"),StringValue.of(recipe.getId().toString())); - data.put(StringValue.of("craft_all"),BooleanValue.of(craftAll)); - return ScreenValue.this.callListener(player,"select_recipe",data); + public boolean onSelectRecipe(final ServerPlayer player, final Recipe recipe, final boolean craftAll) + { + final Map data = new HashMap<>(); + data.put(StringValue.of("recipe"), StringValue.of(recipe.getId().toString())); + data.put(StringValue.of("craft_all"), BooleanValue.of(craftAll)); + return ScreenValue.this.callListener(player, "select_recipe", data); } + @Override - public void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack stack) { - Map data = new HashMap<>(); - data.put(StringValue.of("slot"),NumericValue.of(slotId)); - data.put(StringValue.of("stack"),ValueConversions.of(stack, player.level.registryAccess())); - ScreenValue.this.callListener(ScreenValue.this.player,"slot_update",data); + public void slotChanged(final AbstractContainerMenu handler, final int slotId, final ItemStack stack) + { + final Map data = new HashMap<>(); + data.put(StringValue.of("slot"), NumericValue.of(slotId)); + data.put(StringValue.of("stack"), ValueConversions.of(stack, player.level.registryAccess())); + ScreenValue.this.callListener(ScreenValue.this.player, "slot_update", data); } + @Override - public void dataChanged(AbstractContainerMenu handler, int property, int value) {} + public void dataChanged(final AbstractContainerMenu handler, final int property, final int value) + { + } }); } - private DataSlot getPropertyForType(Class screenHandlerClass, String requiredType, int propertyIndex, String propertyName) { - if(screenHandlerClass.isInstance(this.screenHandler)) { + private DataSlot getPropertyForType(final Class screenHandlerClass, final String requiredType, final int propertyIndex, final String propertyName) + { + if (screenHandlerClass.isInstance(this.screenHandler)) + { return ((ScreenHandlerInterface) this.screenHandler).getProperty(propertyIndex); } - if(!this.isOpen()) { + if (!this.isOpen()) + { throw new InternalExpressionException("Screen property cannot be accessed, because the screen is already closed"); } throw new InternalExpressionException("Screen property " + propertyName + " expected a " + requiredType + " screen."); } - private DataSlot getProperty(String propertyName) { - return switch (propertyName) { + private DataSlot getProperty(final String propertyName) + { + return switch (propertyName) + { case "fuel_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 0, propertyName); case "max_fuel_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 1, propertyName); case "cook_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 2, propertyName); case "max_cook_progress" -> getPropertyForType(AbstractFurnaceMenu.class, "furnace", 3, propertyName); - case "level_cost" -> getPropertyForType(AnvilMenu.class, "anvil", 0, propertyName); - case "page" -> getPropertyForType(LecternMenu.class, "lectern", 0, propertyName); - case "beacon_level" -> getPropertyForType(BeaconMenu.class, "beacon", 0, propertyName); case "primary_effect" -> getPropertyForType(BeaconMenu.class, "beacon", 1, propertyName); case "secondary_effect" -> getPropertyForType(BeaconMenu.class, "beacon", 2, propertyName); - case "brew_time" -> getPropertyForType(BrewingStandMenu.class, "brewing_stand", 0, propertyName); case "brewing_fuel" -> getPropertyForType(BrewingStandMenu.class, "brewing_stand", 1, propertyName); - case "enchantment_power_1" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 0, propertyName); case "enchantment_power_2" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 1, propertyName); case "enchantment_power_3" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 2, propertyName); @@ -274,50 +289,55 @@ public class ScreenValue extends Value { case "enchantment_level_1" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 7, propertyName); case "enchantment_level_2" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 8, propertyName); case "enchantment_level_3" -> getPropertyForType(EnchantmentMenu.class, "enchantment", 9, propertyName); - case "banner_pattern" -> getPropertyForType(LoomMenu.class, "loom", 0, propertyName); - case "stonecutter_recipe" -> getPropertyForType(StonecutterMenu.class, "stonecutter", 0, propertyName); - default -> throw new InternalExpressionException("Invalid screen property: " + propertyName); }; } - public Value queryProperty(String propertyName) { - if(propertyName.equals("name")) return FormattedTextValue.of(this.name); - if(propertyName.equals("open")) return BooleanValue.of(this.isOpen()); - DataSlot property = getProperty(propertyName); + public Value queryProperty(final String propertyName) + { + if (propertyName.equals("name")) + { + return FormattedTextValue.of(this.name); + } + if (propertyName.equals("open")) + { + return BooleanValue.of(this.isOpen()); + } + final DataSlot property = getProperty(propertyName); return NumericValue.of(property.get()); } - public Value modifyProperty(String propertyName, List lv) { - DataSlot property = getProperty(propertyName); - int intValue = NumericValue.asNumber(lv.get(0)).getInt(); + public Value modifyProperty(final String propertyName, final List lv) + { + final DataSlot property = getProperty(propertyName); + final int intValue = NumericValue.asNumber(lv.get(0)).getInt(); property.set(intValue); this.screenHandler.sendAllDataToRemote(); return Value.TRUE; } - public AbstractContainerMenu getScreenHandler() { - return this.screenHandler; - } - - public ServerPlayer getPlayer() { + public ServerPlayer getPlayer() + { return this.player; } - public Container getInventory() { + public Container getInventory() + { return this.inventory; } @Override - public String getString() { + public String getString() + { return this.typestring + "_screen"; } @Override - public boolean getBoolean() { + public boolean getBoolean() + { return this.isOpen(); } @@ -328,92 +348,134 @@ public class ScreenValue extends Value { } @Override - public Tag toTag(boolean force) { - if(this.screenHandler == null) { + public Tag toTag(final boolean force) + { + if (this.screenHandler == null) + { return Value.NULL.toTag(true); } - ListTag nbtList = new ListTag(); - for(int i = 0; i < this.screenHandler.slots.size(); i++) { - ItemStack itemStack = this.screenHandler.getSlot(i).getItem(); + final ListTag nbtList = new ListTag(); + for (int i = 0; i < this.screenHandler.slots.size(); i++) + { + final ItemStack itemStack = this.screenHandler.getSlot(i).getItem(); nbtList.add(itemStack.save(new CompoundTag())); } return nbtList; } - public interface ScarpetScreenHandlerListener extends ContainerListener { + public interface ScarpetScreenHandlerListener extends ContainerListener + { boolean onSlotClick(ServerPlayer player, ClickType actionType, int slot, int button); + boolean onButtonClick(ServerPlayer player, int button); + void onClose(ServerPlayer player); + boolean onSelectRecipe(ServerPlayer player, Recipe recipe, boolean craftAll); } - public static class ScreenHandlerInventory implements Container { - + public static class ScreenHandlerInventory implements Container + { protected AbstractContainerMenu screenHandler; - public ScreenHandlerInventory(AbstractContainerMenu screenHandler) { + public ScreenHandlerInventory(final AbstractContainerMenu screenHandler) + { this.screenHandler = screenHandler; } @Override - public int getContainerSize() { + public int getContainerSize() + { return this.screenHandler.slots.size() + 1; } @Override - public boolean isEmpty() { - for(Slot slot : this.screenHandler.slots) { - if(slot.hasItem() && !slot.getItem().isEmpty()) return false; + public boolean isEmpty() + { + for (final Slot slot : this.screenHandler.slots) + { + if (slot.hasItem() && !slot.getItem().isEmpty()) + { + return false; + } } return this.screenHandler.getCarried().isEmpty(); } @Override - public ItemStack getItem(int slot) { - if(slot == this.getContainerSize()-1) return this.screenHandler.getCarried(); + public ItemStack getItem(final int slot) + { + if (slot == this.getContainerSize() - 1) + { + return this.screenHandler.getCarried(); + } return slot >= -1 && slot < this.getContainerSize() ? this.screenHandler.slots.get(slot).getItem() : ItemStack.EMPTY; } @Override - public ItemStack removeItem(int slot, int amount) { - ItemStack itemStack; - if(slot == this.getContainerSize()-1) + public ItemStack removeItem(final int slot, final int amount) + { + final ItemStack itemStack; + if (slot == this.getContainerSize() - 1) + { itemStack = this.screenHandler.getCarried().split(amount); + } else + { itemStack = ScreenHandlerInventory.splitStack(this.screenHandler.slots, slot, amount); - if (!itemStack.isEmpty()) { + } + if (!itemStack.isEmpty()) + { this.setChanged(); } return itemStack; } @Override - public ItemStack removeItemNoUpdate(int slot) { - ItemStack itemStack; - if(slot == this.getContainerSize()-1) + public ItemStack removeItemNoUpdate(final int slot) + { + final ItemStack itemStack; + if (slot == this.getContainerSize() - 1) + { itemStack = this.screenHandler.getCarried(); + } else + { itemStack = this.screenHandler.slots.get(slot).getItem(); - if (itemStack.isEmpty()) { + } + if (itemStack.isEmpty()) + { return ItemStack.EMPTY; - } else { - if(slot == this.getContainerSize()-1) + } + else + { + if (slot == this.getContainerSize() - 1) + { this.screenHandler.setCarried(ItemStack.EMPTY); + } else + { this.screenHandler.slots.get(slot).set(ItemStack.EMPTY); + } return itemStack; } } @Override - public void setItem(int slot, ItemStack stack) { - if(slot == this.getContainerSize()-1) + public void setItem(final int slot, final ItemStack stack) + { + if (slot == this.getContainerSize() - 1) + { this.screenHandler.setCarried(stack); + } else + { this.screenHandler.slots.get(slot).set(stack); - if (!stack.isEmpty() && stack.getCount() > this.getMaxStackSize()) { + } + if (!stack.isEmpty() && stack.getCount() > this.getMaxStackSize()) + { stack.setCount(this.getMaxStackSize()); } @@ -421,18 +483,21 @@ public class ScreenValue extends Value { } @Override - public void setChanged() { - + public void setChanged() + { } @Override - public boolean stillValid(Player player) { + public boolean stillValid(final Player player) + { return true; } @Override - public void clearContent() { - for(Slot slot : this.screenHandler.slots) { + public void clearContent() + { + for (final Slot slot : this.screenHandler.slots) + { slot.set(ItemStack.EMPTY); } this.screenHandler.setCarried(ItemStack.EMPTY); @@ -440,13 +505,16 @@ public class ScreenValue extends Value { } - public static ItemStack splitStack(List slots, int slot, int amount) { + public static ItemStack splitStack(final List slots, final int slot, final int amount) + { return slot >= 0 && slot < slots.size() && !slots.get(slot).getItem().isEmpty() && amount > 0 ? slots.get(slot).getItem().split(amount) : ItemStack.EMPTY; } } - private static String actionTypeToString(ClickType actionType) { - return switch (actionType) { + private static String actionTypeToString(final ClickType actionType) + { + return switch (actionType) + { case PICKUP -> "pickup"; case QUICK_MOVE -> "quick_move"; case SWAP -> "swap"; diff --git a/src/main/java/carpet/script/value/StringValue.java b/src/main/java/carpet/script/value/StringValue.java index c177aa8d..65b7dc7f 100644 --- a/src/main/java/carpet/script/value/StringValue.java +++ b/src/main/java/carpet/script/value/StringValue.java @@ -7,15 +7,17 @@ public class StringValue extends Value { public static Value EMPTY = StringValue.of(""); - private String str; + private final String str; @Override - public String getString() { + public String getString() + { return str; } @Override - public boolean getBoolean() { + public boolean getBoolean() + { return str != null && !str.isEmpty(); } @@ -25,15 +27,14 @@ public class StringValue extends Value return new StringValue(str); } - public StringValue(String str) + public StringValue(final String str) { this.str = str; } - public static Value of(String value) + public static Value of(final String value) { - if (value == null) return Value.NULL; - return new StringValue(value); + return value == null ? Value.NULL : new StringValue(value); } @Override @@ -43,7 +44,7 @@ public class StringValue extends Value } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { return StringTag.valueOf(str); } diff --git a/src/main/java/carpet/script/value/ThreadValue.java b/src/main/java/carpet/script/value/ThreadValue.java index d5b37683..54231942 100644 --- a/src/main/java/carpet/script/value/ThreadValue.java +++ b/src/main/java/carpet/script/value/ThreadValue.java @@ -6,10 +6,12 @@ import carpet.script.Tokenizer; import carpet.script.exception.ExitStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; + import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; + import net.minecraft.nbt.Tag; public class ThreadValue extends Value @@ -18,21 +20,21 @@ public class ThreadValue extends Value private final long id; private static long sequence = 0L; - public ThreadValue(CompletableFuture taskFuture) + public ThreadValue(final CompletableFuture taskFuture) { this.taskFuture = taskFuture; this.id = sequence++; } - public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List args) + public ThreadValue(final Value pool, final FunctionValue function, final Expression expr, final Tokenizer.Token token, final Context ctx, final List args) { this(getCompletableFutureFromFunction(pool, function, expr, token, ctx, args)); Thread.yield(); } - public static CompletableFuture getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List args) + public static CompletableFuture getCompletableFutureFromFunction(final Value pool, final FunctionValue function, final Expression expr, final Tokenizer.Token token, final Context ctx, final List args) { - ExecutorService executor = ctx.host.getExecutor(pool); + final ExecutorService executor = ctx.host.getExecutor(pool); if (executor == null) { // app is shutting down - no more threads can be spawned. @@ -40,27 +42,22 @@ public class ThreadValue extends Value } else { - return CompletableFuture.supplyAsync( - () -> - { - try - { - return function.execute(ctx, Context.NONE, expr, token, args).evalValue(ctx); - } - catch (ExitStatement exit) - { - // app stopped - return exit.retval; - } - catch (ExpressionException exc) - { - ctx.host.handleExpressionException("Thread failed\n", exc); - return Value.NULL; - } - - }, - ctx.host.getExecutor(pool) - ); + return CompletableFuture.supplyAsync(() -> { + try + { + return function.execute(ctx, Context.NONE, expr, token, args).evalValue(ctx); + } + catch (final ExitStatement exit) + { + // app stopped + return exit.retval; + } + catch (final ExpressionException exc) + { + ctx.host.handleExpressionException("Thread failed\n", exc); + return Value.NULL; + } + }, ctx.host.getExecutor(pool)); } } @@ -87,12 +84,12 @@ public class ThreadValue extends Value { return taskFuture.get(); } - catch (ExitStatement exit) + catch (final ExitStatement exit) { taskFuture.complete(exit.retval); return exit.retval; } - catch (InterruptedException | ExecutionException e) + catch (final InterruptedException | ExecutionException e) { return Value.NULL; } @@ -104,19 +101,19 @@ public class ThreadValue extends Value } @Override - public boolean equals(Object o) + public boolean equals(final Object o) { - if (!(o instanceof ThreadValue)) - return false; - return ((ThreadValue) o).id == this.id; + return o instanceof final ThreadValue tv && tv.id == this.id; } @Override - public int compareTo(Value o) + public int compareTo(final Value o) { - if (!(o instanceof ThreadValue)) + if (!(o instanceof final ThreadValue tv)) + { throw new InternalExpressionException("Cannot compare tasks to other types"); - return (int) (this.id - ((ThreadValue) o).id); + } + return (int) (this.id - tv.id); } @Override @@ -126,9 +123,12 @@ public class ThreadValue extends Value } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { - if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this); + if (!force) + { + throw new NBTSerializableValue.IncompatibleTypeException(this); + } return getValue().toTag(true); } diff --git a/src/main/java/carpet/script/value/UndefValue.java b/src/main/java/carpet/script/value/UndefValue.java index 89c35c97..b41ae53b 100644 --- a/src/main/java/carpet/script/value/UndefValue.java +++ b/src/main/java/carpet/script/value/UndefValue.java @@ -4,14 +4,15 @@ import carpet.script.exception.InternalExpressionException; import com.google.gson.JsonElement; import net.minecraft.nbt.Tag; -public class UndefValue extends NullValue { +public class UndefValue extends NullValue +{ public static final UndefValue UNDEF = new UndefValue(); - private RuntimeException getError() { - return new InternalExpressionException("variable "+boundVariable+" was used before initialization under 'strict' app config"); + private RuntimeException getError() + { + return new InternalExpressionException("variable " + boundVariable + " was used before initialization under 'strict' app config"); } - @Override public String getString() { @@ -43,28 +44,32 @@ public class UndefValue extends NullValue { } @Override - public Value slice(long fromDesc, Long toDesc) { - throw getError(); - } - - @Override - public NumericValue opposite() { - throw getError(); - } - - @Override - public int length() { - throw getError(); - } - - @Override - public int compareTo(Value o) + public Value slice(final long fromDesc, final Long toDesc) { throw getError(); } @Override - public Value in(Value value) { + public NumericValue opposite() + { + throw getError(); + } + + @Override + public int length() + { + throw getError(); + } + + @Override + public int compareTo(final Value o) + { + throw getError(); + } + + @Override + public Value in(final Value value) + { throw getError(); } @@ -81,13 +86,14 @@ public class UndefValue extends NullValue { } @Override - public Tag toTag(boolean force) + public Tag toTag(final boolean force) { throw getError(); } @Override - public Value split(Value delimiter) { + public Value split(final Value delimiter) + { throw getError(); } @@ -98,29 +104,31 @@ public class UndefValue extends NullValue { } @Override - public boolean isNull() { - throw getError(); - } - - @Override - public Value add(Value v) { - throw getError(); - } - - @Override - public Value subtract(Value v) + public boolean isNull() { throw getError(); } @Override - public Value multiply(Value v) + public Value add(final Value v) { throw getError(); } @Override - public Value divide(Value v) + public Value subtract(final Value v) + { + throw getError(); + } + + @Override + public Value multiply(final Value v) + { + throw getError(); + } + + @Override + public Value divide(final Value v) { throw getError(); } diff --git a/src/main/java/carpet/script/value/Value.java b/src/main/java/carpet/script/value/Value.java index c2ed9544..cc0cab1d 100644 --- a/src/main/java/carpet/script/value/Value.java +++ b/src/main/java/carpet/script/value/Value.java @@ -4,23 +4,25 @@ import carpet.CarpetSettings; import carpet.script.exception.InternalExpressionException; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; + import net.minecraft.nbt.Tag; public abstract class Value implements Comparable, Cloneable { - public static NumericValue FALSE = BooleanValue.FALSE; - public static NumericValue TRUE = BooleanValue.TRUE; - public static NumericValue ZERO = new NumericValue(0); - public static NumericValue ONE = new NumericValue(1); + public static final NumericValue FALSE = BooleanValue.FALSE; + public static final NumericValue TRUE = BooleanValue.TRUE; + public static final NumericValue ZERO = new NumericValue(0); + public static final NumericValue ONE = new NumericValue(1); - public static NullValue NULL = NullValue.NULL; - public static UndefValue UNDEF = UndefValue.UNDEF; + public static final NullValue NULL = NullValue.NULL; + public static final UndefValue UNDEF = UndefValue.UNDEF; public String boundVariable; @@ -28,29 +30,32 @@ public abstract class Value implements Comparable, Cloneable { return boundVariable != null; } + public String getVariable() { return boundVariable; } - public Value reboundedTo(String var) + + public Value reboundedTo(final String value) { - Value copy; + final Value copy; try { - copy = (Value)clone(); + copy = (Value) clone(); } - catch (CloneNotSupportedException e) + catch (final CloneNotSupportedException e) { // should not happen CarpetSettings.LOG.error("Failed to clone variable", e); - throw new InternalExpressionException("Variable of type "+getTypeString()+" is not cloneable. Tell gnembon about it, this shoudn't happen"); + throw new InternalExpressionException("Variable of type " + getTypeString() + " is not cloneable. Tell gnembon about it, this shoudn't happen"); } - copy.boundVariable = var; + copy.boundVariable = value; return copy; } - public Value bindTo(String var) + + public Value bindTo(final String value) { - this.boundVariable = var; + this.boundVariable = value; return this; } @@ -64,35 +69,37 @@ public abstract class Value implements Comparable, Cloneable public abstract boolean getBoolean(); - public Value add(Value o) { + public Value add(final Value o) + { if (o instanceof FormattedTextValue) { return FormattedTextValue.combine(this, o); } - String leftStr = this.getString(); - String rightStr = o.getString(); + final String leftStr = this.getString(); + final String rightStr = o.getString(); return new StringValue(leftStr + rightStr); } - public Value subtract(Value v) + + public Value subtract(final Value v) { - return new StringValue(this.getString().replace(v.getString(),"")); + return new StringValue(this.getString().replace(v.getString(), "")); } - public Value multiply(Value v) + + public Value multiply(final Value v) { - if (v instanceof NumericValue || v instanceof ListValue) - { - return v.multiply(this); - } - return new StringValue(this.getString()+"."+v.getString()); + return v instanceof NumericValue || v instanceof ListValue + ? v.multiply(this) + : new StringValue(this.getString() + "." + v.getString()); } - public Value divide(Value v) + + public Value divide(final Value v) { - if (v instanceof NumericValue) + if (v instanceof final NumericValue number) { - String lstr = getString(); - return new StringValue(lstr.substring(0, (int)(lstr.length()/ ((NumericValue) v).getDouble()))); + final String lstr = getString(); + return new StringValue(lstr.substring(0, (int) (lstr.length() / number.getDouble()))); } - return new StringValue(getString()+"/"+v.getString()); + return new StringValue(getString() + "/" + v.getString()); } public Value() @@ -103,18 +110,18 @@ public abstract class Value implements Comparable, Cloneable @Override public int compareTo(final Value o) { - if (o instanceof NumericValue || o instanceof ListValue || o instanceof ThreadValue) - { - return -o.compareTo(this); - } - return getString().compareTo(o.getString()); + return o instanceof NumericValue || o instanceof ListValue || o instanceof ThreadValue + ? -o.compareTo(this) + : getString().compareTo(o.getString()); } @Override // for hashmap key access, and == operator public boolean equals(final Object o) { - if (o instanceof Value) - return this.compareTo((Value) o)==0; + if (o instanceof final Value v) + { + return this.compareTo(v) == 0; + } return false; } @@ -126,50 +133,65 @@ public abstract class Value implements Comparable, Cloneable { throw new InternalExpressionException(boundVariable+ " cannot be assigned a new value"); }*/ - throw new InternalExpressionException(getString()+ " is not a variable"); - + throw new InternalExpressionException(getString() + " is not a variable"); } } - public Value in(Value value1) + public Value in(final Value value1) { final Pattern p; try { p = Pattern.compile(value1.getString()); } - catch (PatternSyntaxException pse) + catch (final PatternSyntaxException pse) { - throw new InternalExpressionException("Incorrect matching pattern: "+pse.getMessage()); + throw new InternalExpressionException("Incorrect matching pattern: " + pse.getMessage()); } final Matcher m = p.matcher(this.getString()); - if (!m.find()) return Value.NULL; - int gc = m.groupCount(); - if (gc == 0) return new StringValue(m.group()); - if (gc == 1) return StringValue.of(m.group(1)); - List groups = new ArrayList<>(gc); + if (!m.find()) + { + return Value.NULL; + } + final int gc = m.groupCount(); + if (gc == 0) + { + return new StringValue(m.group()); + } + if (gc == 1) + { + return StringValue.of(m.group(1)); + } + final List groups = new ArrayList<>(gc); for (int i = 1; i <= gc; i++) { groups.add(StringValue.of(m.group(i))); } return ListValue.wrap(groups); } + public int length() { return getString().length(); } - public Value slice(long fromDesc, Long toDesc) + public Value slice(final long fromDesc, final Long toDesc) { - String value = this.getString(); - int size = value.length(); - int from = ListValue.normalizeIndex(fromDesc, size); - if (toDesc == null) return new StringValue(value.substring(from)); - int to = ListValue.normalizeIndex(toDesc, size+1); - if (from > to) return StringValue.EMPTY; + final String value = this.getString(); + final int size = value.length(); + final int from = ListValue.normalizeIndex(fromDesc, size); + if (toDesc == null) + { + return new StringValue(value.substring(from)); + } + final int to = ListValue.normalizeIndex(toDesc, size + 1); + if (from > to) + { + return StringValue.EMPTY; + } return new StringValue(value.substring(from, to)); } - + public Value split(Value delimiter) { if (delimiter == null) @@ -180,20 +202,20 @@ public abstract class Value implements Comparable, Cloneable { return ListValue.wrap(Arrays.stream(getString().split(delimiter.getString())).map(StringValue::new)); } - catch (PatternSyntaxException pse) + catch (final PatternSyntaxException pse) { - throw new InternalExpressionException("Incorrect pattern for 'split': "+pse.getMessage()); + throw new InternalExpressionException("Incorrect pattern for 'split': " + pse.getMessage()); } } - + public double readDoubleNumber() { - String s = getString(); + final String s = getString(); try { - return Double.valueOf(s); + return Double.parseDouble(s); } - catch (NumberFormatException e) + catch (final NumberFormatException e) { return Double.NaN; } @@ -212,21 +234,20 @@ public abstract class Value implements Comparable, Cloneable @Override public int hashCode() { - String stringVal = getString(); - if (stringVal.isEmpty()) return 0; - return ("s"+stringVal).hashCode(); + final String stringVal = getString(); + return stringVal.isEmpty() ? 0 : ("s" + stringVal).hashCode(); } public Value deepcopy() { try { - return (Value)this.clone(); + return (Value) this.clone(); } - catch (CloneNotSupportedException e) + catch (final CloneNotSupportedException e) { // should never happen - throw new InternalExpressionException("Cannot make a copy of value: "+this); + throw new InternalExpressionException("Cannot make a copy of value: " + this); } } @@ -237,12 +258,18 @@ public abstract class Value implements Comparable, Cloneable return new JsonPrimitive(getString()); } - public boolean isNull() { return false; } + public boolean isNull() + { + return false; + } /** * @return retrieves useful in-run value of an optimized code-base value. * For immutable values (most of them) it can return itself, * but for mutables, it needs to be its copy or deep copy. */ - public Value fromConstant() { return this; } + public Value fromConstant() + { + return this; + } } diff --git a/src/main/java/carpet/script/value/ValueConversions.java b/src/main/java/carpet/script/value/ValueConversions.java index 2535886d..98ddd780 100644 --- a/src/main/java/carpet/script/value/ValueConversions.java +++ b/src/main/java/carpet/script/value/ValueConversions.java @@ -46,6 +46,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.Objective; import net.minecraft.world.scores.criteria.ObjectiveCriteria; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -60,58 +61,65 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; public class ValueConversions { - public static Value of(BlockPos pos) + public static Value of(final BlockPos pos) { return ListValue.of(new NumericValue(pos.getX()), new NumericValue(pos.getY()), new NumericValue(pos.getZ())); } - public static Value of(Vec3 vec) + public static Value of(final Vec3 vec) { return ListValue.of(new NumericValue(vec.x), new NumericValue(vec.y), new NumericValue(vec.z)); } - public static Value of(ColumnPos cpos) { return ListValue.of(new NumericValue(cpos.x()), new NumericValue(cpos.z()));} + public static Value of(final ColumnPos cpos) + { + return ListValue.of(new NumericValue(cpos.x()), new NumericValue(cpos.z())); + } - public static Value of(ServerLevel world) + public static Value of(final ServerLevel world) { return of(world.dimension().location()); } - public static Value of(MaterialColor color) {return ListValue.of(StringValue.of(BlockInfo.mapColourName.get(color)), ofRGB(color.col));} + public static Value of(final MaterialColor color) + { + return ListValue.of(StringValue.of(BlockInfo.mapColourName.get(color)), ofRGB(color.col)); + } - public static Value of(MinMaxBounds range) { return ListValue.of(NumericValue.of(range.getMin()), NumericValue.of(range.getMax()));} + public static Value of(final MinMaxBounds range) + { + return ListValue.of(NumericValue.of(range.getMin()), NumericValue.of(range.getMax())); + } @Deprecated - public static Value of(ItemStack stack) + public static Value of(final ItemStack stack) { - if (stack == null || stack.isEmpty()) - return Value.NULL; - return ListValue.of( + return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of( of(BuiltInRegistries.ITEM.getKey(stack.getItem())), new NumericValue(stack.getCount()), NBTSerializableValue.fromStack(stack) ); } - public static Value of(ItemStack stack, RegistryAccess regs) { - if (stack == null || stack.isEmpty()) - return Value.NULL; - return ListValue.of( + + public static Value of(final ItemStack stack, final RegistryAccess regs) + { + return stack == null || stack.isEmpty() ? Value.NULL : ListValue.of( of(regs.registryOrThrow(Registries.ITEM).getKey(stack.getItem())), new NumericValue(stack.getCount()), NBTSerializableValue.fromStack(stack) ); } - public static Value of(Objective objective) + public static Value of(final Objective objective) { return ListValue.of( StringValue.of(objective.getName()), StringValue.of(objective.getCriteria().getName()) - ); + ); } - public static Value of(ObjectiveCriteria criteria) + public static Value of(final ObjectiveCriteria criteria) { return ListValue.of( StringValue.of(criteria.getName()), @@ -120,20 +128,22 @@ public class ValueConversions } - public static Value of(ParticleOptions particle) + public static Value of(final ParticleOptions particle) { - String repr = particle.writeToString(); - if (repr.startsWith("minecraft:")) return StringValue.of(repr.substring(10)); - return StringValue.of(repr); + final String repr = particle.writeToString(); + return StringValue.of(repr.startsWith("minecraft:") ? repr.substring(10) : repr); } - public static Value ofRGB(int value) {return new NumericValue(value*256+255 );} + public static Value ofRGB(final int value) + { + return new NumericValue(value * 256 + 255); + } - public static Level dimFromValue(Value dimensionValue, MinecraftServer server) + public static Level dimFromValue(final Value dimensionValue, final MinecraftServer server) { if (dimensionValue instanceof EntityValue) { - return ((EntityValue)dimensionValue).getEntity().getCommandSenderWorld(); + return ((EntityValue) dimensionValue).getEntity().getCommandSenderWorld(); } else if (dimensionValue instanceof BlockValue bv) { @@ -148,23 +158,16 @@ public class ValueConversions } else { - String dimString = dimensionValue.getString().toLowerCase(Locale.ROOT); - switch (dimString) - { - case "nether": - case "the_nether": - return server.getLevel(Level.NETHER); - case "end": - case "the_end": - return server.getLevel(Level.END); - case "overworld": - case "over_world": - return server.getLevel(Level.OVERWORLD); - default: + final String dimString = dimensionValue.getString().toLowerCase(Locale.ROOT); + return switch (dimString) { + case "nether", "the_nether" -> server.getLevel(Level.NETHER); + case "end", "the_end" -> server.getLevel(Level.END); + case "overworld", "over_world" -> server.getLevel(Level.OVERWORLD); + default -> { ResourceKey dim = null; - ResourceLocation id = new ResourceLocation(dimString); + final ResourceLocation id = new ResourceLocation(dimString); // not using RegistryKey.of since that one creates on check - for (ResourceKey world : (server.levelKeys())) + for (final ResourceKey world : (server.levelKeys())) { if (id.equals(world.location())) { @@ -173,36 +176,48 @@ public class ValueConversions } } if (dim == null) + { throw new ThrowStatement(dimString, Throwables.UNKNOWN_DIMENSION); - return server.getLevel(dim); - } + } + yield server.getLevel(dim); + } + }; } } - public static Value of(ResourceKey dim) + public static Value of(final ResourceKey dim) { return of(dim.location()); } - public static Value of(TagKey tagKey) { return of(tagKey.location()); } + public static Value of(final TagKey tagKey) + { + return of(tagKey.location()); + } - public static Value of(ResourceLocation id) + public static Value of(final ResourceLocation id) { if (id == null) // should be Value.NULL + { return Value.NULL; + } return new StringValue(simplify(id)); } - public static String simplify(ResourceLocation id) + public static String simplify(final ResourceLocation id) { if (id == null) // should be Value.NULL + { return ""; + } if (id.getNamespace().equals("minecraft")) + { return id.getPath(); + } return id.toString(); } - public static Value of(GlobalPos pos) + public static Value of(final GlobalPos pos) { return ListValue.of( ValueConversions.of(pos.dimension()), @@ -210,14 +225,13 @@ public class ValueConversions ); } - public static Value fromPath(ServerLevel world, Path path) + public static Value fromPath(final ServerLevel world, final Path path) { - List nodes = new ArrayList<>(); - //for (PathNode node: path.getNodes()) + final List nodes = new ArrayList<>(); for (int i = 0, len = path.getNodeCount(); i < len; i++) { - Node node = path.getNode(i); - nodes.add( ListValue.of( + final Node node = path.getNode(i); + nodes.add(ListValue.of( new BlockValue(null, world, node.asBlockPos()), new StringValue(node.type.name().toLowerCase(Locale.ROOT)), new NumericValue(node.costMalus), @@ -227,101 +241,106 @@ public class ValueConversions return ListValue.wrap(nodes); } - public static Value fromTimedMemory(Entity e, long expiry, Object v) + public static Value fromTimedMemory(final Entity e, final long expiry, final Object v) { - Value ret = fromEntityMemory(e, v); - if (ret.isNull() || expiry == Long.MAX_VALUE) return ret; - return ListValue.of(ret, new NumericValue(expiry)); + final Value ret = fromEntityMemory(e, v); + return ret.isNull() || expiry == Long.MAX_VALUE ? ret : ListValue.of(ret, new NumericValue(expiry)); } - private static Value fromEntityMemory(Entity e, Object v) + private static Value fromEntityMemory(final Entity e, Object v) { if (v instanceof GlobalPos pos) { return of(pos); } - if (v instanceof Entity) + if (v instanceof final Entity entity) { - return new EntityValue((Entity)v); + return new EntityValue(entity); } - if (v instanceof BlockPos) + if (v instanceof final BlockPos pos) { - return new BlockValue(null, (ServerLevel) e.getCommandSenderWorld(), (BlockPos) v); + return new BlockValue(null, e.getCommandSenderWorld(), pos); } - if (v instanceof Number) + if (v instanceof final Number number) { - return new NumericValue(((Number) v).doubleValue()); + return new NumericValue(number.doubleValue()); } - if (v instanceof Boolean) + if (v instanceof final Boolean bool) { - return BooleanValue.of((Boolean) v); + return BooleanValue.of(bool); } - if (v instanceof UUID) + if (v instanceof final UUID uuid) { - return ofUUID( (ServerLevel) e.getCommandSenderWorld(), (UUID)v); + return ofUUID((ServerLevel) e.getCommandSenderWorld(), uuid); } - if (v instanceof DamageSource source) + if (v instanceof final DamageSource source) { return ListValue.of( new StringValue(source.getMsgId()), - source.getEntity()==null?Value.NULL:new EntityValue(source.getEntity()) + source.getEntity() == null ? Value.NULL : new EntityValue(source.getEntity()) ); } - if (v instanceof Path) + if (v instanceof final Path path) { - return fromPath((ServerLevel)e.getCommandSenderWorld(), (Path)v); + return fromPath((ServerLevel) e.getCommandSenderWorld(), path); } - if (v instanceof PositionTracker) + if (v instanceof final PositionTracker tracker) { - return new BlockValue(null, e.getCommandSenderWorld(), ((PositionTracker)v).currentBlockPosition()); + return new BlockValue(null, e.getCommandSenderWorld(), tracker.currentBlockPosition()); } - if (v instanceof WalkTarget) + if (v instanceof final WalkTarget target) { return ListValue.of( - new BlockValue(null, e.getCommandSenderWorld(), ((WalkTarget)v).getTarget().currentBlockPosition()), - new NumericValue(((WalkTarget) v).getSpeedModifier()), - new NumericValue(((WalkTarget) v).getCloseEnoughDist()) + new BlockValue(null, e.getCommandSenderWorld(), target.getTarget().currentBlockPosition()), + new NumericValue(target.getSpeedModifier()), + new NumericValue(target.getCloseEnoughDist()) ); } - if (v instanceof NearestVisibleLivingEntities nvle) { + if (v instanceof final NearestVisibleLivingEntities nvle) + { v = StreamSupport.stream(nvle.findAll(entity -> true).spliterator(), false).toList(); } - if (v instanceof Set) + if (v instanceof final Set set) { - v = new ArrayList<>(((Set) v)); + v = new ArrayList<>(set); } - if (v instanceof List l) + if (v instanceof final List l) { - if (l.isEmpty()) return ListValue.of(); - Object el = l.get(0); - if (el instanceof Entity) + if (l.isEmpty()) { - return ListValue.wrap(l.stream().map(o -> new EntityValue((Entity)o))); + return ListValue.of(); } - if (el instanceof GlobalPos) + final Object el = l.get(0); + if (el instanceof final Entity entity) { - return ListValue.wrap(l.stream().map(o -> of((GlobalPos) o))); + return ListValue.wrap(l.stream().map(o -> new EntityValue(entity))); + } + if (el instanceof final GlobalPos pos) + { + return ListValue.wrap(l.stream().map(o -> of(pos))); } } return Value.NULL; } - private static Value ofUUID(ServerLevel entityWorld, UUID uuid) + private static Value ofUUID(final ServerLevel entityWorld, final UUID uuid) { - Entity current = entityWorld.getEntity(uuid); + final Entity current = entityWorld.getEntity(uuid); return ListValue.of( - current == null?Value.NULL:new EntityValue(current), + current == null ? Value.NULL : new EntityValue(current), new StringValue(uuid.toString()) ); } - public static Value of(AABB box) + + public static Value of(final AABB box) { return ListValue.of( ListValue.fromTriple(box.minX, box.minY, box.minZ), ListValue.fromTriple(box.maxX, box.maxY, box.maxZ) ); } - public static Value of(BoundingBox box) + + public static Value of(final BoundingBox box) { return ListValue.of( ListValue.fromTriple(box.minX(), box.minY(), box.minZ()), @@ -329,17 +348,23 @@ public class ValueConversions ); } - public static Value of(StructureStart structure, final RegistryAccess regs) + public static Value of(final StructureStart structure, final RegistryAccess regs) { - if (structure == null || structure == StructureStart.INVALID_START) return Value.NULL; - BoundingBox boundingBox = structure.getBoundingBox(); - if (boundingBox.maxX() < boundingBox.minX() || boundingBox.maxY() < boundingBox.minY() || boundingBox.maxZ() < boundingBox.minZ()) return Value.NULL; - Map ret = new HashMap<>(); - ret.put(new StringValue("box"), of(boundingBox)); - List pieces = new ArrayList<>(); - for (StructurePiece piece : structure.getPieces()) + if (structure == null || structure == StructureStart.INVALID_START) { - BoundingBox box = piece.getBoundingBox(); + return Value.NULL; + } + final BoundingBox boundingBox = structure.getBoundingBox(); + if (boundingBox.maxX() < boundingBox.minX() || boundingBox.maxY() < boundingBox.minY() || boundingBox.maxZ() < boundingBox.minZ()) + { + return Value.NULL; + } + final Map ret = new HashMap<>(); + ret.put(new StringValue("box"), of(boundingBox)); + final List pieces = new ArrayList<>(); + for (final StructurePiece piece : structure.getPieces()) + { + final BoundingBox box = piece.getBoundingBox(); if (box.maxX() >= box.minX() && box.maxY() >= box.minY() && box.maxZ() >= box.minZ()) { pieces.add(ListValue.of( @@ -354,41 +379,51 @@ public class ValueConversions return MapValue.wrap(ret); } - public static Value fromProperty(BlockState state, Property p) + public static Value fromProperty(final BlockState state, final Property p) { - Comparable object = state.getValue(p); - if (object instanceof Boolean || object instanceof Number) return StringValue.of(object.toString()); - if (object instanceof StringRepresentable) + final Comparable object = state.getValue(p); + if (object instanceof Boolean || object instanceof Number) { - return StringValue.of(((StringRepresentable) object).getSerializedName()); + return StringValue.of(object.toString()); } - throw new InternalExpressionException("Unknown property type: "+p.getName()); + if (object instanceof final StringRepresentable stringRepresentable) + { + return StringValue.of(stringRepresentable.getSerializedName()); + } + throw new InternalExpressionException("Unknown property type: " + p.getName()); } - record SlotParam(/* Nullable */ String type, int id) { - public ListValue build() { + record SlotParam(/* Nullable */ String type, int id) + { + public ListValue build() + { return ListValue.of(StringValue.of(type), new NumericValue(id)); } } - private static final Int2ObjectMap slotIdsToSlotParams = new Int2ObjectOpenHashMap<>() {{ + private static final Int2ObjectMap slotIdsToSlotParams = new Int2ObjectOpenHashMap<>() + {{ int n; //covers blocks, player hotbar and inventory, and all default inventories - for(n = 0; n < 54; ++n) { + for (n = 0; n < 54; ++n) + { put(n, new SlotParam(null, n)); } - for(n = 0; n < 27; ++n) { + for (n = 0; n < 27; ++n) + { put(200 + n, new SlotParam("enderchest", n)); } // villager - for(n = 0; n < 8; ++n) { + for (n = 0; n < 8; ++n) + { put(300 + n, new SlotParam(null, n)); } // horse, llamas, donkeys, etc. // two first slots are for saddle and armour - for(n = 0; n < 15; ++n) { + for (n = 0; n < 15; ++n) + { put(500 + n, new SlotParam(null, n + 2)); } // weapon main hand @@ -396,7 +431,8 @@ public class ValueConversions // offhand put(99, new SlotParam("equipment", 5)); // feet, legs, chest, head - for(n = 0; n < 4; ++n) { + for (n = 0; n < 4; ++n) + { put(100 + n, new SlotParam("equipment", n + 1)); } //horse defaults saddle @@ -407,26 +443,25 @@ public class ValueConversions //hashMap.put("horse.chest", 499); }}; - public static Value ofVanillaSlotResult(int itemSlot) + public static Value ofVanillaSlotResult(final int itemSlot) { - SlotParam ret = slotIdsToSlotParams.get(itemSlot); - if (ret == null) return ListValue.of(Value.NULL, new NumericValue(itemSlot)); - return ret.build(); + final SlotParam ret = slotIdsToSlotParams.get(itemSlot); + return ret == null ? ListValue.of(Value.NULL, new NumericValue(itemSlot)) : ret.build(); } - public static Value ofBlockPredicate(RegistryAccess registryAccess, Predicate blockPredicate) + public static Value ofBlockPredicate(final RegistryAccess registryAccess, final Predicate blockPredicate) { - BlockPredicateInterface predicateData = (BlockPredicateInterface) blockPredicate; + final BlockPredicateInterface predicateData = (BlockPredicateInterface) blockPredicate; final Registry blocks = registryAccess.registryOrThrow(Registries.BLOCK); return ListValue.of( - predicateData.getCMBlockState()==null?Value.NULL:of(blocks.getKey(predicateData.getCMBlockState().getBlock())), - predicateData.getCMBlockTagKey()==null?Value.NULL:of(blocks.getTag(predicateData.getCMBlockTagKey()).get().key()), + predicateData.getCMBlockState() == null ? Value.NULL : of(blocks.getKey(predicateData.getCMBlockState().getBlock())), + predicateData.getCMBlockTagKey() == null ? Value.NULL : of(blocks.getTag(predicateData.getCMBlockTagKey()).get().key()), MapValue.wrap(predicateData.getCMProperties()), - predicateData.getCMDataTag() == null?Value.NULL:new NBTSerializableValue(predicateData.getCMDataTag()) + predicateData.getCMDataTag() == null ? Value.NULL : new NBTSerializableValue(predicateData.getCMDataTag()) ); } - public static ItemStack getItemStackFromValue(Value value, boolean withCount, RegistryAccess regs) + public static ItemStack getItemStackFromValue(final Value value, final boolean withCount, final RegistryAccess regs) { if (value.isNull()) { @@ -439,7 +474,7 @@ public class ValueConversions { if (list.length() != 3) { - throw new ThrowStatement("item definition from list of size "+list.length(), Throwables.UNKNOWN_ITEM); + throw new ThrowStatement("item definition from list of size " + list.length(), Throwables.UNKNOWN_ITEM); } final List items = list.getItems(); name = items.get(0).getString(); @@ -447,7 +482,7 @@ public class ValueConversions { count = NumericValue.asNumber(items.get(1)).getInt(); } - Value nbtValue = items.get(2); + final Value nbtValue = items.get(2); if (!nbtValue.isNull()) { nbtTag = ((NBTSerializableValue) NBTSerializableValue.fromValue(nbtValue)).getCompoundTag(); @@ -457,12 +492,12 @@ public class ValueConversions { name = value.getString(); } - ItemInput itemInput = NBTSerializableValue.parseItem(name, nbtTag, regs); + final ItemInput itemInput = NBTSerializableValue.parseItem(name, nbtTag, regs); try { - return itemInput.createItemStack(count,false); + return itemInput.createItemStack(count, false); } - catch (CommandSyntaxException cse) + catch (final CommandSyntaxException cse) { if (!withCount) { @@ -475,31 +510,56 @@ public class ValueConversions } } - public static Value guess(ServerLevel serverWorld, Object o) { + public static Value guess(final ServerLevel serverWorld, final Object o) + { if (o == null) + { return Value.NULL; - if (o instanceof List) - return ListValue.wrap(((List) o).stream().map(oo -> guess(serverWorld, oo))); - if (o instanceof BlockPos) - return new BlockValue(null, serverWorld, (BlockPos)o); - if (o instanceof Entity) - return EntityValue.of((Entity) o); - if (o instanceof Vec3) - return of((Vec3)o); - if (o instanceof Vec3i) - return of(new BlockPos((Vec3i)o)); - if (o instanceof AABB) - return of((AABB)o); - if (o instanceof BoundingBox) - return of((BoundingBox) o); - if (o instanceof ItemStack) - return of((ItemStack)o, serverWorld.registryAccess()); - if (o instanceof Boolean) - return BooleanValue.of((Boolean) o); - if (o instanceof Number) - return NumericValue.of((Number) o); - if (o instanceof ResourceLocation) - return of((ResourceLocation)o); + } + if (o instanceof final List list) + { + return ListValue.wrap(list.stream().map(oo -> guess(serverWorld, oo))); + } + if (o instanceof final BlockPos pos) + { + return new BlockValue(null, serverWorld, pos); + } + if (o instanceof final Entity e) + { + return EntityValue.of(e); + } + if (o instanceof final Vec3 vec3) + { + return of(vec3); + } + if (o instanceof final Vec3i vec3i) + { + return of(new BlockPos(vec3i)); + } + if (o instanceof final AABB aabb) + { + return of(aabb); + } + if (o instanceof final BoundingBox bb) + { + return of(bb); + } + if (o instanceof final ItemStack itemStack) + { + return of(itemStack, serverWorld.registryAccess()); + } + if (o instanceof final Boolean bool) + { + return BooleanValue.of(bool); + } + if (o instanceof final Number number) + { + return NumericValue.of(number); + } + if (o instanceof final ResourceLocation resourceLocation) + { + return of(resourceLocation); + } return StringValue.of(o.toString()); } }