diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 2bffdb88..1b1d109e 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -441,7 +441,7 @@ $ ) $ ); $ lvl $); -/script run global_get_enchantment(players(), 'sharpness') +/script run global_get_enchantment(player(), 'sharpness') ### `Basic Arithmetic Operators + - * /` @@ -1193,7 +1193,7 @@ place of the resulting map element, otherwise current element is skipped.
 map(range(10), _*_)  => [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
-map(players('*'), _+' is stoopid') [gnembon is stoopid, herobrine is stoopid]
+map(player('*'), _+' is stoopid') [gnembon is stoopid, herobrine is stoopid]
 
### `filter(list,expr(_,_i))` @@ -2181,7 +2181,7 @@ set(0,5,0,'bedrock') => bedrock set(l(0,5,0), 'bedrock') => bedrock set(block(0,5,0), 'bedrock') => bedrock scan(0,5,0,0,0,0,set(_,'bedrock')) => 1 -set(pos(players()), 'bedrock') => bedrock +set(pos(player()), 'bedrock') => bedrock set(0,0,0,'bedrock') => 0 // or 1 in overworlds generated in 1.8 and before scan(0,100,0,20,20,20,set(_,'glass')) // filling the area with glass @@ -2351,6 +2351,13 @@ Causes a block to be harvested by a specified player entity. Honors player item tool if applicable. If the entity is not a valid player, no block gets destroyed. If a player is not allowed to break that block, a block doesn't get destroyed either. +### `create_explosion(pos, power?, mode?, fire?, source?, attacker?)` + +Creates an explosion at a given position. Default values of optional parameters are: `'power'` - `4` (TNT power), +`'mode'` (block breaking effect `none`, `destroy` or `break`: `break`, `fire` (whether extra fire blocks should be created) - `false`, +`source` (exploding entity) - `null` and `attacker` (entity responsible for trigerring) - `null`. Explosions created with this +endpoint cannot be captured with `__on_explosion` event, however they will be captured by `__on_explosion_outcome`. + ### `weather()`,`weather(type)`,`weather(type, ticks)` If called with no args, returns `'clear'`, `'rain` or `'thunder'` based on the current weather. If thundering, will @@ -2370,7 +2377,7 @@ and the same can be achieved with `query(entity,'pos')`, but for simplicity `pos
 pos(block(0,5,0)) => l(0,5,0)
-pos(players()) => l(12.3, 45.6, 32.05)
+pos(player()) => l(12.3, 45.6, 32.05)
 pos(block('stone')) => Error: Cannot fetch position of an unrealized block
 
@@ -2620,7 +2627,7 @@ To check if a block is truly loaded, I mean in memory, use `generation_status(x) outside of the playable area, just are not used by any of the game mechanic processes.
-loaded(pos(players()))  => 1
+loaded(pos(player()))  => 1
 loaded(100000,100,1000000)  => 0
 
@@ -3513,6 +3520,12 @@ Regardless of the options selected, the result could be: - block value if block is in reach, or - a coordinate triple if `'exact'` option was used and hit was successful. +### `query(e, 'attribute')` `query(e, 'attribute', name)` + +returns the value of an attribute of the living entity. If the name is not provided, +returns a map of all attributes and values of this entity. If an attribute doesn't apply to the entity, +or the entity is not a living entity, `null` is returned. + ### `query(e, 'brain', memory)` Retrieves brain memory for entity. Possible memory units highly depend on the game version. Brain is availalble @@ -4160,6 +4173,19 @@ at the same time. Triggered right after a lightning strikes. Lightning entity as well as potential horseman trap would already be spawned at that point. `mode` is `true` if the lightning did cause a trap to spawn. +### `__on_explosion(pos, power, source, causer, mode, fire)` + +Event triggered right before explosion takes place and before has any effect on the world. `source` can be an entity causing +the explosion, and `causer` the entity triggering it, +`mode` indicates block effects: `'none'`, `'break'` (drop all blocks), or `'destroy'` - drop few blocks. Event +is not captured when `create_explosion()` is called. + +### `__on_explosion_outcome(pos, power, source, causer, mode, fire, blocks, entities)` +Triggered during the explosion, before any changes to the blocks are done, +but the decision to blow up is already made and entities are already affected. +The parameter `blocks` contains the list of blocks that will blow up (empty if `explosionNoBlockDamage` is set to `true`). +The parameter `entities` contains the list of entities that have been affected by the explosion. Triggered even with `create_explosion()`. + ### `__on_carpet_rule_changes(rule, new_value)` Triggered when a carpet mod rule is changed. It includes extension rules, not using default `/carpet` command, which will then be namespaced as `namespace:rule`. @@ -4188,7 +4214,7 @@ Example events that may cause it to happen is releasing a bow. The event is trig the request, however the `item_tuple` is provided representing the item that the player started with. You can use that and compare with the currently held item for a delta. -### `__on_player_finishes_using_item(player, item_tuple, hand))` +### `__on_player_finishes_using_item(player, item_tuple, hand)` Player using of an item is done. This is controlled server side and is responsible for such events as finishing eating. The event is triggered after confirming that the action is valid, and sending the feedback back to the client, but before triggering it and its effects in game. @@ -5051,47 +5077,86 @@ Synopsis:
 script run create_datapack('foo', 
 {
-    'foo' -> {
-        'bar.json' -> {
-            'c' -> true,
-            'd' -> false,
-            'e' -> {'foo' -> [1,2,3]},
-            'a' -> 'foobar',
-            'b' -> 5
-        }
-    }
+    'foo' -> { 'bar.json' -> {
+        'c' -> true,
+        'd' -> false,
+        'e' -> {'foo' -> [1,2,3]},
+        'a' -> 'foobar',
+        'b' -> 5
+    } }
 })
+
+Custom dimension example: +
 script run create_datapack('funky_world',  {
-    'data' -> {
-        'minecraft' -> {
-            'dimension' -> {
-                'custom_ow.json' -> { 
-                    'type' -> 'minecraft:the_end',
-                    'generator' -> {
-                        'biome_source' -> {
-                             'seed' -> 0,
-                             'large_biomes' -> false,
-                             'type' -> 'minecraft:vanilla_layered'
-                        },
-                        'seed' -> 0,
-                        'settings' -> 'minecraft:nether',
-                        'type' -> 'minecraft:noise'
-                    }
-                }
-            }
-        }
-    }
+    'data' -> { 'minecraft' -> { 'dimension' -> { 'custom_ow.json' -> { 
+        'type' -> 'minecraft:the_end',
+        'generator' -> {
+            'biome_source' -> {
+                 'seed' -> 0,
+                 'large_biomes' -> false,
+                 'type' -> 'minecraft:vanilla_layered'
+            },
+            'seed' -> 0,
+            'settings' -> 'minecraft:nether',
+            'type' -> 'minecraft:noise'
+    } } } } }
 });
 check_hidden_dimensions();  => ['funky_world']
-        
+
+ +Loot table example: +
+script run create_datapack('silverfishes_drop_gravel', {
+    'data' -> { 'minecraft' -> { 'loot_tables' -> { 'entities' -> { 'silverfish.json' -> {
+        'type' -> 'minecraft:entity',
+        'pools' -> [
+            {
+                'rolls' -> {
+                    'min' -> 0,
+                    'max' -> 1
+                },
+                'entries' -> [
+                    {
+                        'type' -> 'minecraft:item',
+                        'name' -> 'minecraft:gravel'
+                    }
+                ]
+            }
+        ]
+    } } } } }
+});
+
+ +Recipe example: +
+script run create_datapack('craftable_cobwebs', {
+    'data' -> { 'scarpet' -> { 'recipes' -> { 'cobweb.json' -> {
+        'type' -> 'crafting_shaped',
+        'pattern' -> [
+            'SSS',
+            'SSS',
+            'SSS'
+        ],
+        'key' -> {
+            'S' -> {
+                'item' -> 'minecraft:string'
+            }
+        },
+        'result' -> {
+            'item' -> 'minecraft:cobweb',
+            'count' -> 1
+        }
+    } } } }
+});
 
### `enable_hidden_dimensions()` The function reads current datapack settings detecting new dimensions defined by these datapacks that have not yet been added to the list of current dimensions and adds them so that they can be used and accessed right away. It doesn't matter how the -datapacks have been added to the game, either with 'create_datapack()' or manually by dropping a datapack file and calling +datapacks have been added to the game, either with `create_datapack()` or manually by dropping a datapack file and calling `/datapack enable` on it. Returns the list of valid dimension names / identifiers that has been added in the process. Fine print: The function should be diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 43aa110e..862ed86d 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -104,7 +104,7 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit public static void onServerLoadedWorlds(MinecraftServer minecraftServer) { - HopperCounter.resetAll(minecraftServer); + HopperCounter.resetAll(minecraftServer, true); extensions.forEach(e -> e.onServerLoadedWorlds(minecraftServer)); scriptServer.initializeForWorld(); } diff --git a/src/main/java/carpet/commands/CounterCommand.java b/src/main/java/carpet/commands/CounterCommand.java index 4417d192..18ad4481 100644 --- a/src/main/java/carpet/commands/CounterCommand.java +++ b/src/main/java/carpet/commands/CounterCommand.java @@ -53,7 +53,7 @@ public class CounterCommand { if (color == null) { - HopperCounter.resetAll(source.getMinecraftServer()); + HopperCounter.resetAll(source.getMinecraftServer(), false); Messenger.m(source, "w Restarted all counters"); } else diff --git a/src/main/java/carpet/commands/SpawnCommand.java b/src/main/java/carpet/commands/SpawnCommand.java index dfd67887..5d1e075e 100644 --- a/src/main/java/carpet/commands/SpawnCommand.java +++ b/src/main/java/carpet/commands/SpawnCommand.java @@ -181,7 +181,7 @@ public class SpawnCommand //counter reset if (counter == null) { - HopperCounter.resetAll(source.getMinecraftServer()); + HopperCounter.resetAll(source.getMinecraftServer(), false); } else { diff --git a/src/main/java/carpet/helpers/HopperCounter.java b/src/main/java/carpet/helpers/HopperCounter.java index 02896fee..a20108a3 100644 --- a/src/main/java/carpet/helpers/HopperCounter.java +++ b/src/main/java/carpet/helpers/HopperCounter.java @@ -1,18 +1,40 @@ package carpet.helpers; +import carpet.CarpetServer; +import carpet.fakes.IngredientInterface; +import carpet.fakes.RecipeManagerInterface; +import carpet.utils.WoolTool; import carpet.utils.Messenger; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongMap; +import net.minecraft.block.AbstractBannerBlock; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.block.MaterialColor; +import net.minecraft.block.Stainable; +import net.minecraft.item.BlockItem; +import net.minecraft.item.DyeItem; +import net.minecraft.item.Items; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.RecipeType; +import net.minecraft.text.Style; +import net.minecraft.text.TextColor; import net.minecraft.util.DyeColor; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.text.BaseText; import net.minecraft.text.TranslatableText; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.List; @@ -23,6 +45,7 @@ import java.util.stream.Collectors; public class HopperCounter { public static final Map COUNTERS; + public static final TextColor WHITE = TextColor.fromFormatting(Formatting.WHITE); static { @@ -35,6 +58,7 @@ public class HopperCounter } public final DyeColor color; + private final String prettyColour; private final Object2LongMap counter = new Object2LongLinkedOpenHashMap<>(); private long startTick; private long startMillis; @@ -42,13 +66,14 @@ public class HopperCounter private HopperCounter(DyeColor color) { + startTick = -1; this.color = color; - // pubSubProvider = new PubSubInfoProvider<>(QuickCarpet.PUBSUB, "carpet.counter." + color.getName(), 0, this::getTotalItems); + this.prettyColour = WoolTool.Material2DyeName.getOrDefault(color.getMaterialColor(),"w ") + color.getName(); } public void add(MinecraftServer server, ItemStack stack) { - if (startTick == 0) + if (startTick < 0) { startTick = server.getWorld(World.OVERWORLD).getTime(); //OW startMillis = System.currentTimeMillis(); @@ -66,11 +91,12 @@ public class HopperCounter // pubSubProvider.publish(); } - public static void resetAll(MinecraftServer server) + public static void resetAll(MinecraftServer server, boolean fresh) { for (HopperCounter counter : COUNTERS.values()) { counter.reset(server); + if (fresh) counter.startTick = -1; } } @@ -96,47 +122,203 @@ public class HopperCounter public List format(MinecraftServer server, boolean realTime, boolean brief) { - if (counter.isEmpty()) + long ticks = Math.max(realTime ? (System.currentTimeMillis() - startMillis) / 50 : server.getWorld(World.OVERWORLD).getTime() - startTick, 1); //OW + if (startTick < 0 || ticks == 0) { if (brief) { - return Collections.singletonList(Messenger.c("g "+color+": -, -/h, - min ")); + return Collections.singletonList(Messenger.c("b"+prettyColour,"w : ","gi -, -/h, - min ")); } - return Collections.singletonList(Messenger.s(String.format("No items for %s yet", color.getName()))); + return Collections.singletonList(Messenger.c(prettyColour, "w hasn't started counting yet")); } long total = getTotalItems(); - long ticks = Math.max(realTime ? (System.currentTimeMillis() - startMillis) / 50 : server.getWorld(World.OVERWORLD).getTime() - startTick, 1); //OW if (total == 0) { if (brief) { - return Collections.singletonList(Messenger.c(String.format("c %s: 0, 0/h, %.1f min ", color, ticks / (20.0 * 60.0)))); + return Collections.singletonList(Messenger.c("b"+prettyColour,"w : ","wb 0","w , ","wb 0","w /h, ", String.format("wb %.1f ", ticks / (20.0 * 60.0)), "w min")); } - return Collections.singletonList(Messenger.c(String.format("w No items for %s yet (%.2f min.%s)", - color.getName(), ticks / (20.0 * 60.0), (realTime ? " - real time" : "")), + return Collections.singletonList(Messenger.c("w No items for ", prettyColour, String.format("w yet (%.2f min.%s)", + ticks / (20.0 * 60.0), (realTime ? " - real time" : "")), "nb [X]", "^g reset", "!/counter " + color.getName() +" reset")); } if (brief) { - return Collections.singletonList(Messenger.c(String.format("c %s: %d, %d/h, %.1f min ", - color.getName(), total, total * (20 * 60 * 60) / ticks, ticks / (20.0 * 60.0)))); + return Collections.singletonList(Messenger.c("b"+prettyColour,"w : ", + "wb "+total,"w , ", + "wb "+(total * (20 * 60 * 60) / ticks),"w /h, ", + String.format("wb %.1f ", ticks / (20.0 * 60.0)), "w min" + )); } List items = new ArrayList<>(); - items.add(Messenger.c(String.format("w Items for %s (%.2f min.%s), total: %d, (%.1f/h):", - color, ticks*1.0/(20*60), (realTime?" - real time":""), total, total*1.0*(20*60*60)/ticks), + items.add(Messenger.c("w Items for ", prettyColour, + "w (",String.format("wb %.2f", ticks*1.0/(20*60)), "w min"+(realTime?" - real time":"")+"), ", + "w total: ", "wb "+total, "w , (",String.format("wb %.1f",total*1.0*(20*60*60)/ticks),"w /h):", "nb [X]", "^g reset", "!/counter "+color+" reset" )); items.addAll(counter.object2LongEntrySet().stream().sorted((e, f) -> Long.compare(f.getLongValue(), e.getLongValue())).map(e -> { - BaseText itemName = new TranslatableText(e.getKey().getTranslationKey()); + Item item = e.getKey(); + BaseText itemName = new TranslatableText(item.getTranslationKey()); + Style itemStyle = itemName.getStyle(); + TextColor color = guessColor(item); + itemName.setStyle((color != null) ? itemStyle.withColor(color) : itemStyle.withItalic(true)); long count = e.getLongValue(); - return Messenger.c("w - ", itemName, String.format("w : %d, %.1f/h", - count, - count * (20.0 * 60.0 * 60.0) / ticks)); + return Messenger.c("g - ", itemName, + "g : ","wb "+count,"g , ", + String.format("wb %.1f", count * (20.0 * 60.0 * 60.0) / ticks), "w /h" + ); }).collect(Collectors.toList())); return items; } + public static int appropriateColor(int color) + { + if (color == 0) return MaterialColor.WHITE.color; + int r = (color >> 16 & 255); + int g = (color >> 8 & 255); + int b = (color & 255); + if (r < 70) r = 70; + if (g < 70) g = 70; + if (b < 70) b = 70; + return (r << 16) + (g << 8) + b; + } + + private static final ImmutableMap DEFAULTS = new ImmutableMap.Builder() + .put(Items.DANDELION, Blocks.YELLOW_WOOL) + .put(Items.POPPY, Blocks.RED_WOOL) + .put(Items.BLUE_ORCHID, Blocks.LIGHT_BLUE_WOOL) + .put(Items.ALLIUM, Blocks.MAGENTA_WOOL) + .put(Items.AZURE_BLUET, Blocks.SNOW_BLOCK) + .put(Items.RED_TULIP, Blocks.RED_WOOL) + .put(Items.ORANGE_TULIP, Blocks.ORANGE_WOOL) + .put(Items.WHITE_TULIP, Blocks.SNOW_BLOCK) + .put(Items.PINK_TULIP, Blocks.PINK_WOOL) + .put(Items.OXEYE_DAISY, Blocks.SNOW_BLOCK) + .put(Items.CORNFLOWER, Blocks.BLUE_WOOL) + .put(Items.WITHER_ROSE, Blocks.BLACK_WOOL) + .put(Items.LILY_OF_THE_VALLEY, Blocks.WHITE_WOOL) + .put(Items.BROWN_MUSHROOM, Blocks.BROWN_MUSHROOM_BLOCK) + .put(Items.RED_MUSHROOM, Blocks.RED_MUSHROOM_BLOCK) + .put(Items.STICK, Blocks.OAK_PLANKS) + .put(Items.GOLD_INGOT, Blocks.GOLD_BLOCK) + .put(Items.IRON_INGOT, Blocks.IRON_BLOCK) + .put(Items.DIAMOND, Blocks.DIAMOND_BLOCK) + .put(Items.NETHERITE_INGOT, Blocks.NETHERITE_BLOCK) + .put(Items.SUNFLOWER, Blocks.YELLOW_WOOL) + .put(Items.LILAC, Blocks.MAGENTA_WOOL) + .put(Items.ROSE_BUSH, Blocks.RED_WOOL) + .put(Items.PEONY, Blocks.PINK_WOOL) + .put(Items.CARROT, Blocks.ORANGE_WOOL) + .put(Items.APPLE,Blocks.RED_WOOL) + .put(Items.WHEAT,Blocks.HAY_BLOCK) + .put(Items.PORKCHOP, Blocks.PINK_WOOL) + .put(Items.RABBIT,Blocks.PINK_WOOL) + .put(Items.CHICKEN,Blocks.WHITE_TERRACOTTA) + .put(Items.BEEF,Blocks.NETHERRACK) + .put(Items.ENCHANTED_GOLDEN_APPLE,Blocks.GOLD_BLOCK) + .put(Items.COD,Blocks.WHITE_TERRACOTTA) + .put(Items.SALMON,Blocks.ACACIA_PLANKS) + .put(Items.ROTTEN_FLESH,Blocks.BROWN_WOOL) + .put(Items.PUFFERFISH,Blocks.YELLOW_TERRACOTTA) + .put(Items.TROPICAL_FISH,Blocks.ORANGE_WOOL) + .put(Items.POTATO,Blocks.WHITE_TERRACOTTA) + .put(Items.MUTTON, Blocks.RED_WOOL) + .put(Items.BEETROOT,Blocks.NETHERRACK) + .put(Items.MELON_SLICE,Blocks.MELON) + .put(Items.POISONOUS_POTATO,Blocks.SLIME_BLOCK) + .put(Items.SPIDER_EYE,Blocks.NETHERRACK) + .put(Items.GUNPOWDER,Blocks.GRAY_WOOL) + .put(Items.SCUTE,Blocks.LIME_WOOL) + .put(Items.FEATHER,Blocks.WHITE_WOOL) + .put(Items.FLINT,Blocks.BLACK_WOOL) + .put(Items.LEATHER,Blocks.SPRUCE_PLANKS) + .put(Items.GLOWSTONE_DUST,Blocks.GLOWSTONE) + .put(Items.PAPER,Blocks.WHITE_WOOL) + .put(Items.BRICK,Blocks.BRICKS) + .put(Items.INK_SAC,Blocks.BLACK_WOOL) + .put(Items.SNOWBALL,Blocks.SNOW_BLOCK) + .put(Items.WATER_BUCKET,Blocks.WATER) + .put(Items.LAVA_BUCKET,Blocks.LAVA) + .put(Items.MILK_BUCKET,Blocks.WHITE_WOOL) + .put(Items.CLAY_BALL, Blocks.CLAY) + .put(Items.COCOA_BEANS,Blocks.COCOA) + .put(Items.BONE,Blocks.BONE_BLOCK) + .put(Items.COD_BUCKET,Blocks.BROWN_TERRACOTTA) + .put(Items.PUFFERFISH_BUCKET,Blocks.YELLOW_TERRACOTTA) + .put(Items.SALMON_BUCKET,Blocks.PINK_TERRACOTTA) + .put(Items.TROPICAL_FISH_BUCKET,Blocks.ORANGE_TERRACOTTA) + .put(Items.SUGAR,Blocks.WHITE_WOOL) + .put(Items.BLAZE_POWDER,Blocks.GOLD_BLOCK) + .put(Items.ENDER_PEARL,Blocks.WARPED_PLANKS) + .put(Items.NETHER_STAR,Blocks.DIAMOND_BLOCK) + .put(Items.PRISMARINE_CRYSTALS,Blocks.SEA_LANTERN) + .put(Items.PRISMARINE_SHARD,Blocks.PRISMARINE) + .put(Items.RABBIT_HIDE,Blocks.OAK_PLANKS) + .put(Items.CHORUS_FRUIT,Blocks.PURPUR_BLOCK) + .put(Items.SHULKER_SHELL,Blocks.SHULKER_BOX) + .put(Items.NAUTILUS_SHELL,Blocks.BONE_BLOCK) + .put(Items.HEART_OF_THE_SEA,Blocks.CONDUIT) + .put(Items.HONEYCOMB,Blocks.HONEYCOMB_BLOCK) + .put(Items.NAME_TAG,Blocks.BONE_BLOCK) + .put(Items.TOTEM_OF_UNDYING,Blocks.YELLOW_TERRACOTTA) + .put(Items.TRIDENT,Blocks.PRISMARINE) + .put(Items.GHAST_TEAR,Blocks.WHITE_WOOL) + .put(Items.PHANTOM_MEMBRANE,Blocks.BONE_BLOCK) + .put(Items.EGG,Blocks.BONE_BLOCK) + //.put(Items.,Blocks.) + .build(); + + public static TextColor fromItem(Item item) + { + if (DEFAULTS.containsKey(item)) return TextColor.fromRgb(appropriateColor(DEFAULTS.get(item).getDefaultMaterialColor().color)); + if (item instanceof DyeItem) return TextColor.fromRgb(appropriateColor(((DyeItem) item).getColor().getMaterialColor().color)); + Block block = null; + Identifier id = Registry.ITEM.getId(item); + if (item instanceof BlockItem) + { + block = ((BlockItem) item).getBlock(); + } + else if (Registry.BLOCK.containsId(id)) + { + block = Registry.BLOCK.get(id); + } + if (block != null) + { + if (block instanceof AbstractBannerBlock) return TextColor.fromRgb(appropriateColor(((AbstractBannerBlock) block).getColor().getMaterialColor().color)); + if (block instanceof Stainable) return TextColor.fromRgb(appropriateColor( ((Stainable) block).getColor().getMaterialColor().color)); + return TextColor.fromRgb(appropriateColor( block.getDefaultMaterialColor().color)); + } + return null; + } + + public static TextColor guessColor(Item item) + { + TextColor direct = fromItem(item); + if (direct != null) return direct; + if (CarpetServer.minecraft_server == null) return WHITE; + Identifier id = Registry.ITEM.getId(item); + for (RecipeType type: Registry.RECIPE_TYPE) + { + for (Recipe r: ((RecipeManagerInterface) CarpetServer.minecraft_server.getRecipeManager()).getAllMatching(type, id)) + { + for (Ingredient ingredient: r.getPreviewInputs()) + { + for (Collection stacks : ((IngredientInterface) (Object) ingredient).getRecipeStacks()) + { + for (ItemStack iStak : stacks) + { + TextColor cand = fromItem(iStak.getItem()); + if (cand != null) + return cand; + } + } + } + } + } + return null; + } + public static HopperCounter getCounter(String color) { try @@ -152,6 +334,6 @@ public class HopperCounter public long getTotalItems() { - return counter.values().stream().mapToLong(Long::longValue).sum(); + return counter.isEmpty()?0:counter.values().stream().mapToLong(Long::longValue).sum(); } } diff --git a/src/main/java/carpet/script/utils/FixedCommandSource.java b/src/main/java/carpet/script/utils/FixedCommandSource.java index c88e9874..939cb9d2 100644 --- a/src/main/java/carpet/script/utils/FixedCommandSource.java +++ b/src/main/java/carpet/script/utils/FixedCommandSource.java @@ -80,12 +80,6 @@ public class FixedCommandSource extends ServerCommandSource return this; } - @Override - public ServerCommandSource mergeConsumers(ResultConsumer consumer, BinaryOperator> binaryOperator) - { - return this.withConsumer(binaryOperator.apply(this.resultConsumer, consumer)); - } - @Override public ServerCommandSource withSilent() { @@ -190,6 +184,7 @@ public class FixedCommandSource extends ServerCommandSource @Override public void onCommandComplete(CommandContext context, boolean success, int result) { + if (this.resultConsumer != null) resultConsumer.onCommandComplete(context, success, result); } @Override diff --git a/src/main/java/carpet/utils/WoolTool.java b/src/main/java/carpet/utils/WoolTool.java index d6b51d48..6f6e6fd4 100644 --- a/src/main/java/carpet/utils/WoolTool.java +++ b/src/main/java/carpet/utils/WoolTool.java @@ -21,6 +21,25 @@ import java.util.List; public class WoolTool { private static final HashMap Material2Dye = new HashMap<>(); + + public static final HashMap Material2DyeName = new HashMap(){{ + put(MaterialColor.WHITE, "w "); + put(MaterialColor.ORANGE, "#F9801D "); + put(MaterialColor.MAGENTA, "m "); + put(MaterialColor.LIGHT_BLUE, "t "); + put(MaterialColor.YELLOW, "y "); + put(MaterialColor.LAPIS, "l "); + put(MaterialColor.PINK, "#FFACCB "); + put(MaterialColor.GRAY, "f "); + put(MaterialColor.LIGHT_GRAY, "g "); + put(MaterialColor.CYAN, "c "); + put(MaterialColor.PURPLE, "p "); + put(MaterialColor.BLUE, "v "); + put(MaterialColor.BROWN, "#835432 "); + put(MaterialColor.GREEN, "e "); + put(MaterialColor.RED, "r "); + put(MaterialColor.BLACK, "k "); + }}; static { for (DyeColor color: DyeColor.values()) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index c98709eb..2eee13cc 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -3,13 +3,14 @@ "id": "carpet", "version": "${version}", - "name": "Carpet Mod in Fabric", + "name": "Carpet Mod", "description": "Carpet made out of fabric", "authors": [ "gnembon, ..." ], "contact": { "homepage": "https://github.com/gnembon/fabric-carpet", + "issues": "https://github.com/gnembon/fabric-carpet/issues", "sources": "https://github.com/gnembon/fabric-carpet" }, @@ -33,8 +34,5 @@ "depends": { "minecraft": "1.17.x", "fabricloader": ">=0.7.1" - }, - "suggests": { - "flamingo": "*" } }