diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index c0bde734..01d76d85 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -4120,7 +4120,8 @@ that have functions listed above will be automatically bounded and unbounded whe ### `scoreboard()`, `scoreboard(objective)`, `scoreboard(objective, key)`, `scoreboard(objective, key, value)` Displays or modifies individual scoreboard values. With no arguments, returns the list of current objectives. -With specified `objective`, lists all keys (players) associated with current objective. With specified `objective`, +With specified `objective`, lists all keys (players) associated with current objective, or `null` if objective does not exist. +With specified `objective` and `key`, returns current value of the objective for a given player (key). With additional `value` sets a new scoreboard value, returning previous value associated with the `key`. @@ -4143,7 +4144,8 @@ for the objective. ### `scoreboard_display(place, objective)` -sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. +sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. If objective is invalid, +returns `null`. # Auxiliary aspects Collection of other methods that control smaller, yet still important aspects of the game diff --git a/docs/scarpet/api/Scoreboard.md b/docs/scarpet/api/Scoreboard.md index b638fb93..d2feb12d 100644 --- a/docs/scarpet/api/Scoreboard.md +++ b/docs/scarpet/api/Scoreboard.md @@ -3,7 +3,8 @@ ### `scoreboard()`, `scoreboard(objective)`, `scoreboard(objective, key)`, `scoreboard(objective, key, value)` Displays or modifies individual scoreboard values. With no arguments, returns the list of current objectives. -With specified `objective`, lists all keys (players) associated with current objective. With specified `objective`, +With specified `objective`, lists all keys (players) associated with current objective, or `null` if objective does not exist. +With specified `objective` and `key`, returns current value of the objective for a given player (key). With additional `value` sets a new scoreboard value, returning previous value associated with the `key`. @@ -26,4 +27,5 @@ for the objective. ### `scoreboard_display(place, objective)` -sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. +sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. If objective is invalid, +returns `null`. diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index c0af18b7..8e5ed54a 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -73,6 +73,7 @@ public class CarpetSettings /* These will be turned when events can be added / removed in code + Then also gotta remember to remove relevant rules @Rule( desc = "Turns on internal camera path tracing app", @@ -97,9 +98,29 @@ public class CarpetSettings appSource = "ai_tracker" ) public static boolean commandAITracker = true; + + @Rule( + desc = "Enables /draw commands", + extra = { + "... allows for drawing simple shapes or", + "other shapes which are sorta difficult to do normally" + }, + appSource = "draw", + category = {FEATURE, SCARPET, COMMAND} + ) + public static String commandDraw = "true"; + + @Rule( + desc = "Enables /distance command to measure in game distance between points", + extra = "Also enables brown carpet placement action if 'carpets' rule is turned on as well", + appSource = "distance", + category = {FEATURE, SCARPET, COMMAND} + ) + public static String commandDistance = "true"; */ + @Rule(desc = "Gbhs sgnf sadsgras fhskdpri!", category = EXPERIMENTAL) public static boolean superSecretSetting = false; @@ -378,6 +399,7 @@ public class CarpetSettings @Rule(desc = "Enables /draw commands", extra = {"... allows for drawing simple shapes or","other shapes which are sorta difficult to do normally"}, category = COMMAND) public static String commandDraw = "true"; + @Rule( desc = "Enables /script command", extra = "An in-game scripting API for Scarpet programming language", diff --git a/src/main/java/carpet/commands/ScriptCommand.java b/src/main/java/carpet/commands/ScriptCommand.java index 3b916bba..29973381 100644 --- a/src/main/java/carpet/commands/ScriptCommand.java +++ b/src/main/java/carpet/commands/ScriptCommand.java @@ -244,13 +244,13 @@ public class ScriptCommand suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.listAvailableModules(true),bb)). executes((cc) -> { - boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), true, false, null); + boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, true, false, false); return success?1:0; }). then(literal("global"). executes((cc) -> { - boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), false, false, null); + boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), null, false, false, false); return success?1:0; } ) diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 9280acd0..e31dda16 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -268,6 +268,12 @@ public class CarpetEventServer }; public static final Event NETHER_TICK = new Event("tick_nether", 0, true) { + @Override + public boolean deprecated() + { + return true; + } + @Override public void onTick() { @@ -279,6 +285,11 @@ public class CarpetEventServer }; public static final Event ENDER_TICK = new Event("tick_ender", 0, true) { + @Override + public boolean deprecated() + { + return true; + } @Override public void onTick() { @@ -804,6 +815,7 @@ 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 onChunkGenerated(ServerWorld world, Chunk chunk) { } @@ -900,10 +912,10 @@ public class CarpetEventServer private boolean canAddEvent(Event event, ScriptHost host) { + if (event.deprecated()) host.issueDeprecation(event.name+" event"); return !(event.globalOnly && (host.perUser || host.parent != null)); } - public boolean removeEventFromCommand(ServerCommandSource source, String event, String funName) { Event ev = Event.getEvent(event, CarpetServer.scriptServer); diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index b5e33fa7..55dbd2ab 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -57,7 +57,10 @@ public class CarpetScriptHost extends ScriptHost public Map appConfig; public Map appArgTypes; - private CarpetScriptHost(CarpetScriptServer server, Module code, boolean perUser, ScriptHost parent, Map config, Map argTypes) + Function commandValidator; + boolean isRuleApp; + + private CarpetScriptHost(CarpetScriptServer server, Module code, boolean perUser, ScriptHost parent, Map config, Map argTypes, Function commandValidator, boolean isRuleApp) { super(code, perUser, parent); this.saveTimeout = 0; @@ -74,11 +77,13 @@ public class CarpetScriptHost extends ScriptHost } appConfig = config; appArgTypes = argTypes; + this.commandValidator = commandValidator; + this.isRuleApp = isRuleApp; } - public static CarpetScriptHost create(CarpetScriptServer scriptServer, Module module, boolean perPlayer, ServerCommandSource source) + public static CarpetScriptHost create(CarpetScriptServer scriptServer, Module module, boolean perPlayer, ServerCommandSource source, Function commandValidator, boolean isRuleApp) { - CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>()); + CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>(), commandValidator, isRuleApp); // parse code and convert to expression if (module != null) { @@ -169,7 +174,7 @@ public class CarpetScriptHost extends ScriptHost @Override protected ScriptHost duplicate() { - return new CarpetScriptHost(scriptServer, main, false, this, appConfig, appArgTypes); + return new CarpetScriptHost(scriptServer, main, false, this, appConfig, appArgTypes, commandValidator, isRuleApp); } @Override @@ -739,4 +744,15 @@ public class CarpetScriptHost extends ScriptHost { return scriptServer; } + + @Override + public boolean issueDeprecation(String feature) + { + if(super.issueDeprecation(feature)) + { + 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 5b76e085..69fd0327 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -84,6 +84,8 @@ public class CarpetScriptServer registerBuiltInScript(BundledModule.carpetNative("math", true)); registerBuiltInScript(BundledModule.carpetNative("chunk_display", false)); registerBuiltInScript(BundledModule.carpetNative("ai_tracker", false)); + registerBuiltInScript(BundledModule.carpetNative("draw_beta", false)); + registerBuiltInScript(BundledModule.carpetNative("distance_beta", false)); } public CarpetScriptServer(MinecraftServer server) @@ -101,7 +103,7 @@ public class CarpetScriptServer tickStart = 0L; stopAll = false; holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet()); - globalHost = CarpetScriptHost.create(this, null, false, null); + globalHost = CarpetScriptHost.create(this, null, false, null, p -> true, false); } public void initializeForWorld() @@ -117,7 +119,7 @@ public class CarpetScriptServer Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps"); for (String moduleName: listAvailableModules(false)) { - addScriptHost(server.getCommandSource(), moduleName, true, true, null); + addScriptHost(server.getCommandSource(), moduleName, null, true, true, false); } } @@ -168,7 +170,7 @@ public class CarpetScriptServer { for (Module mi : bundledModuleData) { - if (!mi.isLibrary()) moduleNames.add(mi.getName()); + if (!mi.isLibrary() && !mi.getName().endsWith("_beta")) moduleNames.add(mi.getName()); } } File folder = server.getSavePath(WorldSavePath.ROOT).resolve("scripts").toFile(); @@ -193,10 +195,11 @@ public class CarpetScriptServer return modules.get(name); } - public boolean addScriptHost(ServerCommandSource source, String name, boolean perPlayer, boolean autoload, Function commandValidator) + public boolean addScriptHost(ServerCommandSource source, String name, Function commandValidator, + boolean perPlayer, boolean autoload, boolean isRuleApp) { //TODO add per player modules to support player actions better on a server - boolean isRuleApp = commandValidator != null; + if (commandValidator == null) commandValidator = p -> true; long start = System.nanoTime(); name = name.toLowerCase(Locale.ROOT); boolean reload = false; @@ -212,7 +215,7 @@ public class CarpetScriptServer Messenger.m(source, "r Failed to add "+name+" app"); return false; } - CarpetScriptHost newHost = CarpetScriptHost.create(this, module, perPlayer, source); + CarpetScriptHost newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp); if (newHost == null) { Messenger.m(source, "r Failed to add "+name+" app"); @@ -434,13 +437,26 @@ public class CarpetScriptServer } } + static class TransferData + { + boolean perUser; + Function commandValidator; + boolean isRuleApp; + private TransferData(CarpetScriptHost host) + { + perUser = host.perUser; + commandValidator = host.commandValidator; + isRuleApp = host.isRuleApp; + } + } + public void reload(MinecraftServer server) { - Map apps = new HashMap<>(); - modules.forEach((s, h) -> apps.put(s, h.perUser)); + Map apps = new HashMap<>(); + modules.forEach((s, h) -> apps.put(s, new TransferData(h))); apps.keySet().forEach(s -> removeScriptHost(server.getCommandSource(), s, false, false)); CarpetEventServer.Event.clearAllBuiltinEvents(); init(); - apps.forEach((s, pp) -> addScriptHost(server.getCommandSource(), s, pp, false, null)); + apps.forEach((s, data) -> addScriptHost(server.getCommandSource(), s,data.commandValidator, data.perUser,false, data.isRuleApp)); } } diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 3f68c110..2db94244 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -366,7 +366,28 @@ public class Expression public void alias(String copy, String original) { - functions.put(copy, functions.get(original)); + ILazyFunction originalFunction = functions.get(original); + functions.put(copy, new ILazyFunction() + { + @Override + public int getNumParams() + { + return originalFunction.getNumParams(); + } + + @Override + public boolean numParamsVaries() + { + return originalFunction.numParamsVaries(); + } + + @Override + public LazyValue lazyEval(Context c, Integer type, Expression expr, Tokenizer.Token token, List lazyParams) + { + c.host.issueDeprecation(copy+"(...)"); + return originalFunction.lazyEval(c, type, expr, token, lazyParams); + } + }); } diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java index ac0f1803..c55861a6 100644 --- a/src/main/java/carpet/script/ScriptHost.java +++ b/src/main/java/carpet/script/ScriptHost.java @@ -8,9 +8,11 @@ import carpet.script.value.FunctionValue; import carpet.script.value.Value; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -34,6 +36,8 @@ public abstract class ScriptHost private final Map locks = new ConcurrentHashMap<>(); protected boolean inTermination = false; + private final Set deprecations = new HashSet<>(); + public Random getRandom(long aLong) { if (randomizers.size() > 1024) @@ -379,4 +383,14 @@ public abstract class ScriptHost { errorSnooper=null; } + + public static final Logger DEPRECATION_LOG = LogManager.getLogger("Scarpet Deprecation Warnings"); + + public boolean issueDeprecation(String feature) + { + 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"); + return true; + } } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 7e427cd9..6112a2c6 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -577,6 +577,7 @@ public class Auxiliary { expression.addLazyFunction("seed", -1, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; + c.host.issueDeprecation("seed()"); Value ret = new NumericValue(s.getWorld().getSeed()); return (cc, tt) -> ret; }); @@ -785,6 +786,7 @@ public class Auxiliary { boolean shared = false; if (lv.size()>0) { + c.host.issueDeprecation("load_app_data(...) with arguments"); file = recognizeResource(lv.get(0).evalValue(c)); if (lv.size() > 1) { @@ -807,6 +809,7 @@ public class Auxiliary { boolean shared = false; if (lv.size()>1) { + c.host.issueDeprecation("store_app_data(...) with more than one argument"); file = recognizeResource(lv.get(1).evalValue(c)); if (lv.size() > 2) { diff --git a/src/main/java/carpet/script/api/Scoreboards.java b/src/main/java/carpet/script/api/Scoreboards.java index 009df20e..881bfd26 100644 --- a/src/main/java/carpet/script/api/Scoreboards.java +++ b/src/main/java/carpet/script/api/Scoreboards.java @@ -56,7 +56,7 @@ public class Scoreboards { } String objectiveName = lv.get(0).evalValue(c).getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveName); - if (objective == null) throw new InternalExpressionException("Unknown objective: "+objectiveName); + if (objective == null) return LazyValue.NULL; if (lv.size()==1) { Value ret = ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList())); @@ -143,7 +143,7 @@ public class Scoreboards { } String objectiveString = target.getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveString); - if (objective == null) throw new InternalExpressionException("Objective doesn't exist: "+objectiveString); + if (objective == null) return LazyValue.NULL; scoreboard.setObjectiveSlot(slot, objective); return (_c, _t) -> new NumericValue(slot); }); diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index efb81c31..a69324c1 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -543,6 +543,7 @@ public class WorldAccess { // Deprecated, use loaded_status as more indicative expression.addLazyFunction("loaded_ep", -1, (c, t, lv) -> { + c.host.issueDeprecation("loaded_ep(...)"); BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); Value retval = ((CarpetContext)c).s.getWorld().getChunkManager().shouldTickChunk(new ChunkPos(pos))?Value.TRUE : Value.FALSE; return (c_, t_) -> retval; @@ -739,11 +740,12 @@ public class WorldAccess { return (c_, t_) -> Value.FALSE; BlockState finalSourceBlockState = sourceBlockState; BlockPos targetPos = targetLocator.block.getPos(); + Boolean[] result = new Boolean[]{true}; cc.s.getMinecraftServer().submitAndJoin( () -> { Clearable.clear(world.getBlockEntity(targetPos)); - world.setBlockState(targetPos, finalSourceBlockState, 2); - if (finalData != null) + boolean success = world.setBlockState(targetPos, finalSourceBlockState, 2); + if (success && finalData != null) { BlockEntity be = world.getBlockEntity(targetPos); if (be != null) @@ -756,7 +758,9 @@ public class WorldAccess { be.markDirty(); } } + result[0] = success; }); + if (!result[0]) return LazyValue.FALSE; Value retval = new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos()); return (c_, t_) -> retval; }); @@ -962,6 +966,7 @@ public class WorldAccess { // Deprecated for block_state() expression.addLazyFunction("property", -1, (c, t, lv) -> { + c.host.issueDeprecation("property(...)"); BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); if (lv.size() <= locator.offset) @@ -978,6 +983,7 @@ public class WorldAccess { // Deprecated for block_state() expression.addLazyFunction("block_properties", -1, (c, t, lv) -> { + c.host.issueDeprecation("block_properties(...)"); BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); StateManager states = state.getBlock().getStateManager(); diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index bc43f6ea..268bb308 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -190,7 +190,7 @@ public class SettingsManager { if (rule.getBoolValue() || (rule.type == String.class && !rule.get().equals("false"))) { - CarpetServer.scriptServer.addScriptHost(source, rule.scarpetApp, false, false, s -> canUseCommand(s, rule.get())); + CarpetServer.scriptServer.addScriptHost(source, rule.scarpetApp, s -> canUseCommand(s, rule.get()), false, false, true); } else { CarpetServer.scriptServer.removeScriptHost(source, rule.scarpetApp, false, true); } diff --git a/src/main/java/carpet/settings/Validator.java b/src/main/java/carpet/settings/Validator.java index 6f90bd60..3afa6dd4 100644 --- a/src/main/java/carpet/settings/Validator.java +++ b/src/main/java/carpet/settings/Validator.java @@ -38,8 +38,8 @@ public abstract class Validator return newValue; } @Override - public String description() { return "Its a client command so can be issued when connecting to non-carpet servers. " + - "In client-server setting it will only affect the executing player, so each player needs to type it" + + public String description() { return "Its a client command so can be issued and potentially be effective when connecting to non-carpet/vanilla servers. " + + "In these situations (on vanilla servers) it will only affect the executing player, so each player needs to type it" + " separately for the desired effect";} } diff --git a/src/main/resources/assets/carpet/scripts/camera.sc b/src/main/resources/assets/carpet/scripts/camera.sc index 0ba530e6..7d146cdd 100644 --- a/src/main/resources/assets/carpet/scripts/camera.sc +++ b/src/main/resources/assets/carpet/scripts/camera.sc @@ -638,14 +638,14 @@ save_as(file) -> //otherwise mojang will interpret 0.0d as 0i and fail to insert put(path_nbt:'points', point_nbt, _i); ); - store_app_data(path_nbt, file); + write_file(file, 'nbt', path_nbt); 'stored path as '+file; ); // loads path under the local file that load(file) -> ( - path_nbt = load_app_data(file); + path_nbt = read_file(file, 'nbt'); if (!path_nbt, exit('No path to load: '+file)); new_points = map(get(path_nbt, 'points[]'), l(_:'pos[]', _:'duration', _:'type')); if (!new_points || first(new_points, length(_:0) != 5), diff --git a/src/main/resources/assets/carpet/scripts/distance_beta.sc b/src/main/resources/assets/carpet/scripts/distance_beta.sc new file mode 100644 index 00000000..b1b3bc6d --- /dev/null +++ b/src/main/resources/assets/carpet/scripts/distance_beta.sc @@ -0,0 +1,91 @@ +import('math','_euclidean','_manhattan','_round'); + +__config()->{ + 'commands'->{ + 'from '->'set_start', + 'from to '->'_calculate', + 'to '->_(end_pos)->(_calculate(null,end_pos)), + 'toggle_line'->'_toggle_line' + }, + 'arguments' -> { + 'start' -> {'type' -> 'location'}, + 'end' -> {'type' -> 'location'} + } +}; + +global_start=null; +global_end=null; + +global_show_line=false; + +__mktp(pos) -> str('!/tp %.6f %.6f %.6f', pos); + +set_start(pos)->( + global_start = pos; + global_end = null; + print(player(),format('gi Initial point set to: ', 'g '+pos, __mktp(pos))) +); + +_toggle_line()->( + global_show_line= !global_show_line; + if(global_show_line, + print('Toggled lines on'); + _draw_line() + , // else + print('Toggled lines off') + ); +); + +_calculate(start_pos, end_pos)->( + if(start_pos!=null, + set_start(start_pos); + calculate(end_pos) + , // else + if(global_start, + calculate(end_pos), + print(player(),format('r There was no initial point for '+player())); + set_start(end_pos) + ) + ) +); + +__on_player_places_block(player, item_tuple, hand, block) ->( + if(block=='brown_carpet' && system_info('world_carpet_rules'):'carpets'=='true', + effective_pos = pos(block)+[0.5, 0, 0.5]; + if(global_start==null||player~'sneaking',//wont complain for first carpet + set_start(effective_pos), + _calculate(null, effective_pos) + ) + ) +); + +calculate(end_pos)->( + global_end = end_pos; + manhattan = _round(_manhattan(global_start, global_end),0.001);//rounding to nearest 0.01 for precision, but not ridiculous decimal places + spherical = _round(_euclidean(global_start, global_end), 0.001); + //useful for chunk distances etc. + cylindrical = _round(_euclidean(global_start, [global_end:0, global_start:1, global_end:2]), 0.001); + + + print(player(),format( + 'w Distance between ', + 'c '+str('[%.1f, %.1f, %.1f]', global_start), __mktp(global_start), + 'w and ', + 'c '+str('[%.1f, %.1f, %.1f]', global_end), __mktp(global_end), 'w :\n', + 'w - Spherical: ', 'wb '+spherical+'\n', + 'w - Cylindrical: ', 'wb '+cylindrical+'\n', + 'w - Manhattan: ', 'wb '+manhattan + )); + + schedule(0,'_draw_line'); +); + +_draw_line()->( + if(global_show_line,//It will always draw from the global positions, so it will turn on if there is a line + if ( global_start && global_end, + draw_shape('line',20,'from',global_start,'to',global_end, 'player',player()); + draw_shape('label',20,'pos',global_end,'text',_round(_euclidean(global_start,global_end),0.001)); + ); + schedule(20,'_draw_line') + ) +); diff --git a/src/main/resources/assets/carpet/scripts/draw_beta.sc b/src/main/resources/assets/carpet/scripts/draw_beta.sc new file mode 100644 index 00000000..ff819431 --- /dev/null +++ b/src/main/resources/assets/carpet/scripts/draw_beta.sc @@ -0,0 +1,142 @@ +import('math','_euclidean_sq','_vec_length'); + +__config() -> { + 'commands'->{ + 'sphere
'->['draw_sphere',null,true], + 'sphere
replace '->['draw_sphere',true], + 'ball
'->['draw_sphere',null,false], + 'ball
replace '->['draw_sphere',false], + 'diamond
'->['draw_diamond',null], + 'diamond
replace '->'draw_diamond', + 'pyramid
'->['draw_pyramid',null, true], + 'pyramid
replace '->['draw_pyramid', true], + 'cone
'->['draw_pyramid',null, false], + 'cone
replace '->['draw_pyramid', false], + 'cuboid
'->['draw_prism', null, true], + 'cuboid
replace '->['draw_prism', true], + 'cylinder
'->['draw_prism', null, false], + 'cylinder
replace '->['draw_prism', false] + }, + 'arguments'->{ + 'center'->{'type'->'pos', 'loaded'->'true'}, + 'radius'->{'type'->'int', 'suggest'->[], 'min'->0},//to avoid default suggestions + 'replacement'->{'type'->'block'}, + 'height'->{'type'->'int', 'suggest'->[],'min'->0}, + 'orientation'->{'type'->'term', 'suggest'->['x','y','z']}, + 'pointing'->{'type'->'term','suggest'->['up','down']}, + 'hollow'->{'type'->'term','suggest'->['hollow','solid']}, + }, + 'scope'->'global' +}; + + +//"Boilerplate" code + +set_block(x, y, z, block, replacement)-> ( + if(block != block(x, y, z), + without_updates( if (set([x, y, z],block), + global_affected += [x, y, z]; + )); + ); +); + +global_affected = []; + +affected(player) -> ( + affected = length(global_affected); + print(player,format('gi Filled ' + affected + ' blocks')); + + if(system_info('world_carpet_rules'):'fillUpdates', + for(global_affected,update(_));//updating if fillUpdates is true + ); + + global_affected = []; + affected +); + +length_sq(vec) -> reduce(vec, _a + _*_, 0); + +fill_flat(pos, offset, dr, rectangle, orientation, block, hollow, replacement)->( + r = floor(dr); + drsq = dr^2; + if(orientation=='x', + scan(pos,0,-r,-r, + if((!hollow && (rectangle || _y^2 + _z^2 <= drsq))||//if not hollow, vry simple + (hollow && ((rectangle && (abs(_y) == r || abs(_z) ==r)) || //If hollow and it's a rectangle + (!rectangle && (_y^2 + _z^2 <= drsq && (abs(_y)+1)^ 2 + (abs(_z)+1)^2 >= drsq)))),//If hollow and not rectangle + set_block(_x+offset,_y,_z,block, replacement) + ) + ), + orientation == 'y', + scan(pos,-r,0,-r, + if((!hollow && (rectangle || _x^2 + _z^2 <= drsq))||//if not hollow, vry simple + (hollow && ((rectangle && (abs(_x) == r || abs(_z) ==r)) || //If hollow and it's a rectangle + (!rectangle && (_x^2 + _z^2 <= drsq && (abs(_x)+1)^ 2 + (abs(_z)+1)^2 >= drsq)))),//If hollow and not rectangle + set_block(_x,_y+offset,_z,block, replacement) + ) + ), + orientation == 'z', + scan(pos,-r,-r,0, + if((!hollow && (rectangle || _y^2 + _x^2 <= drsq))||//if not hollow, vry simple + (hollow && ((rectangle && (abs(_y) == r || abs(_x) ==r)) || //If hollow and it's a rectangle + (!rectangle && (_y^2 + _x^2 <= drsq && (abs(_y)+1)^ 2 + (abs(_x)+1)^2 >= drsq)))),//If hollow and not rectangle + set_block(_x,_y,_z+offset,block, replacement) + ) + ), + print(player(),format('r Error while running command: orientation can only be "x", "y" or "z", '+orientation+' is invalid.')); + global_affected = []; + ); +); + +//drawing commands + +draw_sphere(centre, radius, block, replacement, hollow)->( + scan(centre,[radius,radius,radius], + l = length_sq([_x,_y,_z]-centre); + if((l<=radius^2+radius) && (!hollow || l>=radius^2-radius), + set_block(_x, _y, _z, block, replacement) + ) + ); + + affected(player()); +); + +draw_diamond(pos, radius, block, replacement)->( + + c_for(r=0, r( + + hollow = fill_type=='hollow'; + pointup = pointing=='up'; + + for(range(height), + r = if(pointup, radius - radius * _ / height -1, radius * _ / height); + fill_flat(pos, _, r, is_square, orientation, block, if((pointup&&_==0)||(!pointup && _==height-1),false,hollow),replacement)//Always close bottom off + ); + affected(player()) +); + +draw_prism(pos, rad, height, orientation, block, fill_type, replacement, is_square)->( + + hollow = fill_type =='hollow'; + radius = rad+0.5; + + for(range(height), + fill_flat(pos, _, radius, is_square, orientation, block, if(_==0 || _==height-1,false,hollow), replacement)//Always close ends off + ); + affected(player()) +); diff --git a/src/main/resources/assets/carpet/scripts/math.scl b/src/main/resources/assets/carpet/scripts/math.scl index adef1621..4af9ae32 100644 --- a/src/main/resources/assets/carpet/scripts/math.scl +++ b/src/main/resources/assets/carpet/scripts/math.scl @@ -1,3 +1,5 @@ _euclidean_sq(vec1, vec2) -> reduce(vec1 - vec2, _a + _*_, 0); _euclidean(vec1, vec2) -> sqrt(reduce(vec1 - vec2, _a + _*_, 0)); -_vec_length(vec) -> sqrt(reduce(vec, _a + _*_, 0)); \ No newline at end of file +_manhattan(vec1, vec2) -> reduce(vec1-vec2,_a+abs(_),0); +_vec_length(vec) -> sqrt(reduce(vec, _a + _*_, 0)); +_round(num,precision) -> round(num/precision)*precision;