From ac6b3c7f483df29c62bcf2de175bd478a7fb0f04 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 6 Dec 2020 23:40:02 -0400 Subject: [PATCH 1/6] apps can be organized in floders in your shared instance space. --- docs/scarpet/api/Overview.md | 3 ++- src/main/java/carpet/script/CarpetScriptServer.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/scarpet/api/Overview.md b/docs/scarpet/api/Overview.md index 7c08b451..4f1da73c 100644 --- a/docs/scarpet/api/Overview.md +++ b/docs/scarpet/api/Overview.md @@ -6,7 +6,8 @@ Here is the gist of the Minecraft related functions. Otherwise the CarpetScript ## App structure The main delivery method for scarpet programs into the game is in the form of apps in `*.sc` files located in the world `scripts` -folder. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world. +folder, flat. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world, +and here you can actually organize them in folders. When loaded (via `/script load` command, etc.), the game will run the content of the app once, regardless of its scope (more about the app scopes below), without executing of any functions, unless called directly, and with the exception of the `__config()` function, if present, which will be executed once. Loading the app will also bind specific diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index d7090999..b515489e 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -149,7 +149,7 @@ public class CarpetScriptServer { Path globalFolder = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts"); Files.createDirectories(globalFolder); - scriptPath = Files.list(globalFolder) + scriptPath = Files.walk(globalFolder) .filter(script -> script.getFileName().toString().equalsIgnoreCase(name + ".sc") || (allowLibraries && script.getFileName().toString().equalsIgnoreCase(name + ".scl"))) .findFirst(); @@ -194,7 +194,7 @@ public class CarpetScriptServer try { Path worldScripts = server.getSavePath(WorldSavePath.ROOT).resolve("scripts"); Files.createDirectories(worldScripts); - Files.walk(worldScripts) + Files.list(worldScripts) .filter(f -> f.toString().endsWith(".sc")) .forEach(f -> moduleNames.add(f.getFileName().toString().replaceFirst("\\.sc$","").toLowerCase(Locale.ROOT))); From a0067d0d6122dcd5394eba1e76f1119773fd45b6 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 7 Dec 2020 00:12:55 -0400 Subject: [PATCH 2/6] added item_list, item_tags to support item tags as well as options for entities to support entity type tags. fixes #382 --- docs/scarpet/api/Entities.md | 20 +++++++--- docs/scarpet/api/Inventories.md | 8 ++++ docs/scarpet/resources/editors/idea/2.txt | 2 + .../scarpet/resources/editors/npp/scarpet.xml | 2 +- src/main/java/carpet/script/api/Entities.java | 25 +++++++----- .../java/carpet/script/api/Inventories.java | 40 +++++++++++++++++++ .../java/carpet/script/value/EntityValue.java | 35 +++++++++++++++- .../script/value/NBTSerializableValue.java | 2 +- 8 files changed, 116 insertions(+), 18 deletions(-) diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 8ecb1af0..0ebc7a59 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -52,7 +52,9 @@ to the `regular` group. * `monster`, `creature`, `ambient`, `water_creature`, `water_ambient`, `misc` - another categorization of living entities based on their spawn group. Negative descriptor resolves to all living types that don't belong to that category. -* Any of the following standard entity types (equivalent to selection from `/summon` vanilla command: +* All entity tags including those provided with datapacks. Built-in entity tags include: `skeletons`, `raiders`, +`beehive_inhabitors` (bee, duh), `arrows` and `impact_projectiles`. +* Any of the following standard entity types (equivalent to selection from `/summon` vanilla command: `area_effect_cloud`, `armor_stand`, `arrow`, `bat`, `bee`, `blaze`, `boat`, `cat`, `cave_spider`, `chest_minecart`, `chicken`, `cod`, `command_block_minecart`, `cow`, `creeper`, `dolphin`, `donkey`, `dragon_fireball`, `drowned`, `egg`, `elder_guardian`, `end_crystal`, `ender_dragon`, `ender_pearl`, `enderman`, `endermite`, `evoker`, @@ -209,13 +211,21 @@ List of entities riding the entity. Entity that `e` rides. -### `query(e, 'tags')` +### `query(e, 'scoreboard_tags')`, `query(e, 'tags')`(deprecated) -List of entity's tags. +List of entity's scoreboard tags. -### `query(e, 'has_tag',tag)` +### `query(e, 'has_scoreboard_tag',tag)`, `query(e, 'has_tag',tag)`(deprecated) -Boolean, true if the entity is marked with `tag`. +Boolean, true if the entity is marked with a `tag` scoreboad tag. + +### `query(e, 'entity_tags')` + +List of entity tags assigned to the type this entity represents. + +### `query(e, 'has_entity_tag', tag)` + +Returns `true` if the entity matches that entity tag, `false` if it doesn't, and `null` if the tag is not valid. ### `query(e, 'is_burning')` diff --git a/docs/scarpet/api/Inventories.md b/docs/scarpet/api/Inventories.md index 1ecc692b..ebe2ed7b 100644 --- a/docs/scarpet/api/Inventories.md +++ b/docs/scarpet/api/Inventories.md @@ -28,6 +28,14 @@ an inventory, all API functions typically do nothing and return null. Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item. +### item_list(tag?) + +With no arguments, returns a list of all items in the game. With an item tag provided, list items matching the tag, or `null` if tag is not valid. + +### item_tags(item, tag?) + +Returns list of tags the item belongs to, or, if tag is provided, `true` if an item maches the tag, `false` if it doesn't and `null` if that's not a valid tag + ### `stack_limit(item)` Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets), diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index e7f1f8f6..397c1760 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -52,6 +52,8 @@ inventory_remove inventory_set inventory_size item_category +item_list +item_tags last_tick_times light liquid diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 46f3a139..759e69d0 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -68,7 +68,7 @@ player spawn entity_id entity_list entity_area entity_selector query modify entity_event entity_load_handler entity_types - stack_limit item_category recipe_data crafting_remaining_item + item_list item_tags stack_limit item_category recipe_data crafting_remaining_item inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index c5a137a9..ccf35938 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -23,6 +23,7 @@ import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; @@ -34,6 +35,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -183,8 +185,9 @@ public class Entities { expression.addLazyFunction("entity_list", 1, (c, t, lv) -> { String who = lv.get(0).evalValue(c).getString(); - EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who); - List entityList = ((CarpetContext)c).s.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate); + ServerCommandSource source = ((CarpetContext)c).s; + EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, source.getMinecraftServer()); + List entityList = source.getWorld().getEntitiesByType(eDesc.directType, eDesc.filteringPredicate); Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); return (_c, _t ) -> retval; }); @@ -212,8 +215,8 @@ public class Entities { throw new InternalExpressionException("Range of 'entity_area' cannot come from a block argument"); Vec3d range = rangeLocator.vec; Box area = centerBox.expand(range.x, range.y, range.z); - EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who); - List entityList = ((CarpetContext)c).s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate); + EntityValue.EntityClassDescriptor eDesc = EntityValue.getEntityDescriptor(who, cc.s.getMinecraftServer()); + List entityList = cc.s.getWorld().getEntitiesByType(eDesc.directType, area,eDesc.filteringPredicate); Value retval = ListValue.wrap(entityList.stream().map(EntityValue::new).collect(Collectors.toList())); return (_c, _t ) -> retval; }); @@ -238,7 +241,9 @@ public class Entities { Value v = lv.get(0).evalValue(c); if (!(v instanceof EntityValue)) throw new InternalExpressionException("First argument to query should be an entity"); - String what = lv.get(1).evalValue(c).getString(); + String what = lv.get(1).evalValue(c).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); @@ -269,11 +274,13 @@ public class Entities { return (cc, tt) -> v; }); - expression.addFunction("entity_types", (lv) -> + expression.addLazyFunction("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).listValue; + String desc = (lv.size() == 1)?lv.get(0).evalValue(c).getString():"*"; + Value ret = EntityValue.getEntityDescriptor(desc, ((CarpetContext) c).s.getMinecraftServer()).listValue; + return (_c, _t) -> ret; }); expression.addLazyFunction("entity_load_handler", -1, (c, t, lv) -> @@ -285,7 +292,7 @@ public class Entities { ? ((ListValue) entityValue).getItems().stream().map(Value::getString).collect(Collectors.toList()) : Collections.singletonList(entityValue.getString()); Set> types = new HashSet<>(); - descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s).typeList)); + descriptors.forEach(s -> types.addAll(EntityValue.getEntityDescriptor(s, ((CarpetContext) c).s.getMinecraftServer()).typeList)); FunctionArgument funArg = FunctionArgument.findIn(c, expression.module, lv, 1, true, false); CarpetEventServer events = ((CarpetScriptHost)c.host).getScriptServer().events; if (funArg.function == null) diff --git a/src/main/java/carpet/script/api/Inventories.java b/src/main/java/carpet/script/api/Inventories.java index b5f6bfb4..fb4983ae 100644 --- a/src/main/java/carpet/script/api/Inventories.java +++ b/src/main/java/carpet/script/api/Inventories.java @@ -12,6 +12,7 @@ import carpet.script.value.NullValue; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; +import carpet.script.value.ValueConversions; import com.google.common.collect.Sets; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.argument.ItemStackArgument; @@ -32,6 +33,7 @@ import net.minecraft.recipe.ShapedRecipe; import net.minecraft.recipe.ShapelessRecipe; import net.minecraft.recipe.SpecialCraftingRecipe; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.tag.TagManager; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; import net.minecraft.util.math.Vec3d; @@ -40,6 +42,7 @@ import net.minecraft.util.registry.Registry; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; public class Inventories { public static void apply(Expression expression) @@ -60,6 +63,43 @@ public class Inventories { return (_c, _t) -> res; }); + expression.addLazyFunction("item_list", -1, (c, t, lv) -> + { + if (lv.size() == 0) + { + Value res = ListValue.wrap(Registry.ITEM.getIds().stream().map(ValueConversions::of).collect(Collectors.toList())); + return (cc, tt) -> res; + } + CarpetContext cc = (CarpetContext)c; + TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); + String tag = lv.get(0).evalValue(c).getString(); + net.minecraft.tag.Tag itemTag = tagManager.getItems().getTag(new Identifier(tag)); + if (itemTag == null) return LazyValue.NULL; + Value ret = ListValue.wrap(itemTag.values().stream().map(b -> ValueConversions.of(Registry.ITEM.getId(b))).collect(Collectors.toList())); + return (_c, _t) -> ret; + }); + + expression.addLazyFunction("item_tags", -1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + TagManager tagManager = cc.s.getMinecraftServer().getTagManager(); + if (lv.size() == 0) + { + Value ret = ListValue.wrap(tagManager.getItems().getTagIds().stream().map(ValueConversions::of).collect(Collectors.toList())); + return (_c, _t) -> ret; + } + Item item = NBTSerializableValue.parseItem(lv.get(0).evalValue(c).getString()).getItem(); + if (lv.size() == 1) + { + Value ret = ListValue.wrap(tagManager.getItems().getTagsFor(item).stream().map(ValueConversions::of).collect(Collectors.toList())); + return (_c, _t) -> ret; + } + String tag = lv.get(1).evalValue(c).getString(); + net.minecraft.tag.Tag itemTag = tagManager.getItems().getTag(new Identifier(tag)); + if (itemTag == null) return LazyValue.NULL; + return item.isIn(itemTag)?LazyValue.TRUE:LazyValue.FALSE; + }); + expression.addLazyFunction("recipe_data", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index c30ff0aa..89535a7c 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -223,10 +223,28 @@ public class EntityValue extends Value return entity.hashCode(); } - public static EntityClassDescriptor getEntityDescriptor(String who) + public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server) { EntityClassDescriptor eDesc = EntityClassDescriptor.byName.get(who); - if (eDesc == null) throw new InternalExpressionException(who+" is not a valid entity descriptor"); + if (eDesc == null) + { + boolean positive = true; + if (who.startsWith("!")) + { + positive = false; + who = who.substring(1); + } + net.minecraft.tag.Tag> eTag = server.getTagManager().getEntityTypes().getTag(new Identifier(who)); + if (eTag == null) throw new InternalExpressionException(who+" is not a valid entity descriptor"); + if (positive) + { + return new EntityClassDescriptor(null, e -> eTag.contains(e.getType()) && e.isAlive(), eTag.values().stream()); + } + else + { + return new EntityClassDescriptor(null, e -> !eTag.contains(e.getType()) && e.isAlive(), Registry.ENTITY_TYPE.stream().filter(et -> !eTag.contains(et))); + } + } return eDesc; //TODO add more here like search by tags, or type //if (who.startsWith('tag:')) @@ -401,8 +419,21 @@ public class EntityValue extends Value put("passengers", (e, a) -> ListValue.wrap(e.getPassengerList().stream().map(EntityValue::new).collect(Collectors.toList()))); put("mount", (e, a) -> (e.getVehicle()!=null)?new EntityValue(e.getVehicle()):Value.NULL); put("unmountable", (e, a) -> new NumericValue(((EntityInterface)e).isPermanentVehicle())); + // deprecated put("tags", (e, a) -> ListValue.wrap(e.getScoreboardTags().stream().map(StringValue::new).collect(Collectors.toList()))); + + put("scoreboard_tags", (e, a) -> ListValue.wrap(e.getScoreboardTags().stream().map(StringValue::new).collect(Collectors.toList()))); + put("entity_tags", (e, a) -> ListValue.wrap(e.getServer().getTagManager().getEntityTypes().getTagsFor(e.getType()).stream().map(ValueConversions::of).collect(Collectors.toList()))); + // deprecated put("has_tag", (e, a) -> new NumericValue(e.getScoreboardTags().contains(a.getString()))); + + put("has_scoreboard_tag", (e, a) -> new NumericValue(e.getScoreboardTags().contains(a.getString()))); + put("has_entity_tag", (e, a) -> { + net.minecraft.tag.Tag> tag = e.getServer().getTagManager().getEntityTypes().getTag(new Identifier(a.getString())); + if (tag == null) return Value.NULL; + return new NumericValue(e.getType().isIn(tag)); + }); + put("yaw", (e, a)-> new NumericValue(e.yaw)); put("head_yaw", (e, a)-> { if (e instanceof LivingEntity) diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 938acd20..877300dc 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -267,7 +267,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } } - private static Map itemCache = new HashMap<>(); + private static final Map itemCache = new HashMap<>(); public static ItemStackArgument parseItem(String itemString) { From f400c9c0063b32a83486f21411d08dd53320f278 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 7 Dec 2020 04:16:59 +0000 Subject: [PATCH 3/6] Merge docs for 'added item_list, item_tags to support item tags as well as options for entities to support entity type tags. fixes #382' --- docs/scarpet/Full.md | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index c21745b7..e8c7e07f 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -1757,7 +1757,8 @@ Here is the gist of the Minecraft related functions. Otherwise the CarpetScript ## App structure The main delivery method for scarpet programs into the game is in the form of apps in `*.sc` files located in the world `scripts` -folder. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world. +folder, flat. In singleplayer, you can also save apps in `.minecraft/config/carpet/scripts` for them to be available in any world, +and here you can actually organize them in folders. When loaded (via `/script load` command, etc.), the game will run the content of the app once, regardless of its scope (more about the app scopes below), without executing of any functions, unless called directly, and with the exception of the `__config()` function, if present, which will be executed once. Loading the app will also bind specific @@ -2919,7 +2920,9 @@ to the `regular` group. * `monster`, `creature`, `ambient`, `water_creature`, `water_ambient`, `misc` - another categorization of living entities based on their spawn group. Negative descriptor resolves to all living types that don't belong to that category. -* Any of the following standard entity types (equivalent to selection from `/summon` vanilla command: +* All entity tags including those provided with datapacks. Built-in entity tags include: `skeletons`, `raiders`, +`beehive_inhabitors` (bee, duh), `arrows` and `impact_projectiles`. +* Any of the following standard entity types (equivalent to selection from `/summon` vanilla command: `area_effect_cloud`, `armor_stand`, `arrow`, `bat`, `bee`, `blaze`, `boat`, `cat`, `cave_spider`, `chest_minecart`, `chicken`, `cod`, `command_block_minecart`, `cow`, `creeper`, `dolphin`, `donkey`, `dragon_fireball`, `drowned`, `egg`, `elder_guardian`, `end_crystal`, `ender_dragon`, `ender_pearl`, `enderman`, `endermite`, `evoker`, @@ -3076,13 +3079,21 @@ List of entities riding the entity. Entity that `e` rides. -### `query(e, 'tags')` +### `query(e, 'scoreboard_tags')`, `query(e, 'tags')`(deprecated) -List of entity's tags. +List of entity's scoreboard tags. -### `query(e, 'has_tag',tag)` +### `query(e, 'has_scoreboard_tag',tag)`, `query(e, 'has_tag',tag)`(deprecated) -Boolean, true if the entity is marked with `tag`. +Boolean, true if the entity is marked with a `tag` scoreboad tag. + +### `query(e, 'entity_tags')` + +List of entity tags assigned to the type this entity represents. + +### `query(e, 'has_entity_tag', tag)` + +Returns `true` if the entity matches that entity tag, `false` if it doesn't, and `null` if the tag is not valid. ### `query(e, 'is_burning')` @@ -3744,6 +3755,14 @@ an inventory, all API functions typically do nothing and return null. Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item. +### item_list(tag?) + +With no arguments, returns a list of all items in the game. With an item tag provided, list items matching the tag, or `null` if tag is not valid. + +### item_tags(item, tag?) + +Returns list of tags the item belongs to, or, if tag is provided, `true` if an item maches the tag, `false` if it doesn't and `null` if that's not a valid tag + ### `stack_limit(item)` Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets), From e8a6b8936fb6a085411462da28cbbabf1e1f0b5b Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 7 Dec 2020 00:32:08 -0400 Subject: [PATCH 4/6] as per discussion, since scripts can now be stowed in the global bin, it makes sense for apps to behave like datapacks. fixes #613 --- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/java/carpet/script/CarpetScriptHost.java | 2 +- src/main/java/carpet/script/CarpetScriptServer.java | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index fbe1ac98..78257a10 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -427,7 +427,7 @@ public class CarpetSettings extra = "if /script is enabled", category = SCARPET ) - public static boolean scriptsAutoload = false; + public static boolean scriptsAutoload = true; @Rule(desc = "Enables /player command to control/spawn players", category = COMMAND) public static String commandPlayer = "ops"; diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index 4a5a02ef..12eff864 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -217,7 +217,7 @@ public class CarpetScriptHost extends ScriptHost if (!(ret instanceof MapValue)) return false; Map config = ((MapValue) ret).getMap(); setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player")); - persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.FALSE).getBoolean(); + persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.TRUE).getBoolean(); // read custom arguments Value arguments = config.get(StringValue.of("arguments")); if (arguments != null) diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index b515489e..736ed338 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -122,7 +122,6 @@ public class CarpetScriptServer }); if (CarpetSettings.scriptsAutoload) { - Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps"); for (String moduleName: listAvailableModules(false)) { addScriptHost(server.getCommandSource(), moduleName, null, true, true, false); From 522d97168856ed85a0597db8f60cbc390a4b97c9 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 7 Dec 2020 01:11:55 -0400 Subject: [PATCH 5/6] added startup and shutdown events. fixes #586 --- docs/scarpet/api/Events.md | 7 ++++++ src/main/java/carpet/CarpetServer.java | 4 ++-- .../java/carpet/script/CarpetEventServer.java | 24 +++++++++++++++++++ .../carpet/script/CarpetScriptServer.java | 3 ++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/docs/scarpet/api/Events.md b/docs/scarpet/api/Events.md index b337090d..18e3f2ba 100644 --- a/docs/scarpet/api/Events.md +++ b/docs/scarpet/api/Events.md @@ -32,6 +32,13 @@ if it accepts required number of parameters. Global events will be handled once per app that is with `'global'` scope. With `player` scoped apps, each player instance is responsible independently from handling their events, so a global event may be executed multiple times for each player. +### `__on_server_starts()` +Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`. + +### `__on_server_shuts_down()` +Event triggers when the server started the shutdown process, before `__on_close()` is executed. Unlike `__on_close()`, it doesn't +trigger with `/reload`. + ### `__on_tick()` Event triggers at the beginning of each tick, located in the overworld. You can use `in_dimension()` to access other dimensions from there. diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index d069fe81..773b61e3 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -102,9 +102,9 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit public static void onServerLoadedWorlds(MinecraftServer minecraftServer) { + HopperCounter.resetAll(minecraftServer); extensions.forEach(e -> e.onServerLoadedWorlds(minecraftServer)); scriptServer.initializeForWorld(); - HopperCounter.resetAll(minecraftServer); } public static void tick(MinecraftServer server) @@ -169,9 +169,9 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit public static void onServerClosed(MinecraftServer server) { + if (scriptServer != null) scriptServer.onClose(); ServerNetworkHandler.close(); currentCommandDispatcher = null; - if (scriptServer != null) scriptServer.onClose(); LoggerRegistry.stopLoggers(); extensions.forEach(e -> e.onServerClosed(server)); diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 04599e8d..11e89c03 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -309,6 +309,30 @@ public class CarpetEventServer return events; } + public static final Event START = new Event("server_starts", 0, true) + { + @Override + public void onTick() + { + handler.call(Collections::emptyList, () -> + CarpetServer.minecraft_server.getCommandSource(). + withWorld(CarpetServer.minecraft_server.getWorld(World.OVERWORLD)) + ); + } + }; + + public static final Event SHUTDOWN = new Event("server_shuts_down", 0, true) + { + @Override + public void onTick() + { + handler.call(Collections::emptyList, () -> + CarpetServer.minecraft_server.getCommandSource(). + withWorld(CarpetServer.minecraft_server.getWorld(World.OVERWORLD)) + ); + } + }; + public static final Event TICK = new Event("tick", 0, true) { @Override diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 736ed338..41b2fc34 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -127,7 +127,7 @@ public class CarpetScriptServer addScriptHost(server.getCommandSource(), moduleName, null, true, true, false); } } - + CarpetEventServer.Event.START.onTick(); } public Module getModule(String name, boolean allowLibraries) @@ -489,6 +489,7 @@ public class CarpetScriptServer public void onClose() { + CarpetEventServer.Event.SHUTDOWN.onTick(); for (ScriptHost host : modules.values()) { host.onClose(); From fb2602eea8e5bba8de69d80c362b885ec5ab19f8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 7 Dec 2020 05:12:40 +0000 Subject: [PATCH 6/6] Merge docs for 'added startup and shutdown events. fixes #586' --- docs/scarpet/Full.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index e8c7e07f..78b53a0d 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3959,6 +3959,13 @@ if it accepts required number of parameters. Global events will be handled once per app that is with `'global'` scope. With `player` scoped apps, each player instance is responsible independently from handling their events, so a global event may be executed multiple times for each player. +### `__on_server_starts()` +Event triggers after world is loaded and after all startup apps have started. It won't be triggered with `/reload`. + +### `__on_server_shuts_down()` +Event triggers when the server started the shutdown process, before `__on_close()` is executed. Unlike `__on_close()`, it doesn't +trigger with `/reload`. + ### `__on_tick()` Event triggers at the beginning of each tick, located in the overworld. You can use `in_dimension()` to access other dimensions from there.