From 85a34fdefacba6f0fbcfd4959f71f122c55409a2 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 6 Feb 2020 09:33:46 -0400 Subject: [PATCH 1/4] added profile command --- src/main/java/carpet/CarpetServer.java | 14 ++------ src/main/java/carpet/CarpetSettings.java | 7 ++++ .../java/carpet/commands/ProfileCommand.java | 33 +++++++++++++++++++ .../java/carpet/commands/TickCommand.java | 4 +-- 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 src/main/java/carpet/commands/ProfileCommand.java diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 1e55bc6c..b4e47369 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -5,18 +5,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -import carpet.commands.CameraModeCommand; -import carpet.commands.CounterCommand; -import carpet.commands.DistanceCommand; -import carpet.commands.DrawCommand; -import carpet.commands.InfoCommand; -import carpet.commands.LogCommand; -import carpet.commands.MobAICommand; -import carpet.commands.PerimeterInfoCommand; -import carpet.commands.PlayerCommand; -import carpet.commands.ScriptCommand; -import carpet.commands.SpawnCommand; -import carpet.commands.TickCommand; +import carpet.commands.*; import carpet.helpers.TickSpeed; import carpet.logging.LoggerRegistry; import carpet.script.CarpetScriptServer; @@ -89,6 +78,7 @@ public class CarpetServer // static for now - easier to handle all around the co public static void registerCarpetCommands(CommandDispatcher dispatcher) { TickCommand.register(dispatcher); + ProfileCommand.register(dispatcher); CounterCommand.register(dispatcher); LogCommand.register(dispatcher); SpawnCommand.register(dispatcher); diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index f3c22b4c..cfd2795c 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -231,6 +231,13 @@ public class CarpetSettings @Rule(desc = "Enables /tick command to control game clocks", category = COMMAND) public static String commandTick = "true"; + @Rule( + desc = "Enables /profile command to monitor game performance", + extra = "subset of /tick command capabilities", + category = COMMAND + ) + public static String commandProfile = "true"; + @Rule(desc = "Enables /log command to monitor events via chat and overlays", category = COMMAND) public static String commandLog = "true"; diff --git a/src/main/java/carpet/commands/ProfileCommand.java b/src/main/java/carpet/commands/ProfileCommand.java new file mode 100644 index 00000000..6a4dc2f4 --- /dev/null +++ b/src/main/java/carpet/commands/ProfileCommand.java @@ -0,0 +1,33 @@ +package carpet.commands; + +import carpet.CarpetSettings; +import carpet.settings.SettingsManager; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import net.minecraft.server.command.ServerCommandSource; + +import static carpet.commands.TickCommand.healthEntities; +import static carpet.commands.TickCommand.healthReport; +import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger; +import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class ProfileCommand +{ + public static void register(CommandDispatcher dispatcher) + { + LiteralArgumentBuilder literalargumentbuilder = literal("profile"). + requires((player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandProfile)). + executes( (c) -> healthReport(c.getSource(), 100)). + then(literal("health"). + executes( (c) -> healthReport(c.getSource(), 100)). + then(argument("ticks", integer(20,24000)). + executes( (c) -> healthReport(c.getSource(), getInteger(c, "ticks"))))). + then(literal("entities"). + executes((c) -> healthEntities(c.getSource(), 100)). + then(argument("ticks", integer(20,24000)). + executes((c) -> healthEntities(c.getSource(), getInteger(c, "ticks"))))); + dispatcher.register(literalargumentbuilder); + } +} diff --git a/src/main/java/carpet/commands/TickCommand.java b/src/main/java/carpet/commands/TickCommand.java index b9e47b9a..ac65b7bd 100644 --- a/src/main/java/carpet/commands/TickCommand.java +++ b/src/main/java/carpet/commands/TickCommand.java @@ -129,13 +129,13 @@ public class TickCommand return 1; } - private static int healthReport(ServerCommandSource source, int ticks) + public static int healthReport(ServerCommandSource source, int ticks) { CarpetProfiler.prepare_tick_report(source, ticks); return 1; } - private static int healthEntities(ServerCommandSource source, int ticks) + public static int healthEntities(ServerCommandSource source, int ticks) { CarpetProfiler.prepare_entity_report(source, ticks); return 1; From 73680247f44eb3481e2428b48e4995a4f275643c Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 6 Feb 2020 09:35:08 -0400 Subject: [PATCH 2/4] b --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index b413fb09..603b6ab3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.6+build.181 # Mod Properties - mod_version = 1.3.9+v200206 + mod_version = 1.3.9+v200206b maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index cfd2795c..b07f7195 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -32,7 +32,7 @@ import static carpet.settings.RuleCategory.DISPENSER; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.9+v200206"; + public static final String carpetVersion = "1.3.9+v200206b"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; From 67d71e26c101093bebea842367ebd39d261b7e63 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 6 Feb 2020 16:54:36 -0400 Subject: [PATCH 3/4] destroy rework, needs testing --- .../java/carpet/script/CarpetExpression.java | 86 ++++++++++++------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 2bb24ce0..218233cf 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -43,6 +43,15 @@ import net.minecraft.block.CommandBlock; import net.minecraft.block.JigsawBlock; import net.minecraft.block.StructureBlock; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.MiningToolItem; +import net.minecraft.item.ShearsItem; +import net.minecraft.item.SwordItem; +import net.minecraft.item.TridentItem; import net.minecraft.network.packet.s2c.play.ContainerSlotUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; import net.minecraft.command.arguments.ItemStackArgument; @@ -58,10 +67,6 @@ import net.minecraft.entity.SpawnType; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; @@ -105,8 +110,6 @@ import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.ChunkRandom; -import net.minecraft.loot.context.LootContext; -import net.minecraft.loot.context.LootContextParameters; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; @@ -1243,8 +1246,10 @@ public class CarpetExpression if (lv.size() > locator.offset) how = NumericValue.asNumber(lv.get(locator.offset).evalValue(cc)).getLong(); Item item = Items.DIAMOND_PICKAXE; + boolean playerBreak = false; if (lv.size() > locator.offset+1) { + playerBreak = true; String itemString = lv.get(locator.offset+1).evalValue(c).getString(); item = Registry.ITEM.get(new Identifier(itemString)); if (item == Items.AIR && !itemString.equals("air")) throw new InternalExpressionException("Incorrect item: "+itemString); @@ -1258,37 +1263,56 @@ public class CarpetExpression else tag = NBTSerializableValue.parseString(tagValue.getString()).getCompoundTag(); } - world.removeBlock(where, false); + + ItemStack tool = new ItemStack(item, 1); + if (tag != null) + tool.setTag(tag); + if (playerBreak && state.getHardness(world, where) < 0.0) return LazyValue.FALSE; + boolean removed = world.removeBlock(where, false); + if (!removed) return LazyValue.FALSE; world.playLevelEvent(null, 2001, where, Block.getRawIdFromState(state)); - // WIP tool still mines everything, and only enchantments count. - // need to verify the durability changes - if (how < 0) + boolean toolBroke = false; + boolean dropLoot = true; + if (playerBreak) { - Block.dropStack(world, where, new ItemStack(state.getBlock())); + boolean isUsingEffectiveTool = state.getMaterial().canBreakByHand() || tool.isEffectiveOn(state); + //postMine durability + float hardness = state.getHardness(world, where); + int damageAmount = 0; + if ((item instanceof MiningToolItem && hardness > 0.0) || item instanceof ShearsItem) + { + damageAmount = 1; + } + else if (item instanceof TridentItem || item instanceof SwordItem) + { + damageAmount = 2; + } + toolBroke = damageAmount>0 && tool.damage(damageAmount, world.getRandom(), null); + if (!isUsingEffectiveTool) + dropLoot = false; } - else + + if (dropLoot) { - ItemStack tool = new ItemStack(item, 1); - if (tag != null) - tool.setTag(tag); - if (how > 0) - tool.addEnchantment(Enchantments.FORTUNE,(int)how); - else if (how < 0) - tool.addEnchantment(Enchantments.SILK_TOUCH, 1); - - LootContext.Builder lootContext$Builder_1 = (new LootContext.Builder(world)). - setRandom(world.random). - put(LootContextParameters.POSITION, where). - put(LootContextParameters.BLOCK_STATE, state). - putNullable(LootContextParameters.BLOCK_ENTITY, be). - putNullable(LootContextParameters.THIS_ENTITY, cc.s.getEntity()). - put(LootContextParameters.TOOL, tool); - state.getDroppedStacks(lootContext$Builder_1).forEach((stack) -> Block.dropStack(world, where, stack)); - - //Block.dropStacks(state, world, where, be, cc.s.getEntity(), tool ); + if (how < 0 || (tag != null && EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, tool) > 0)) + { + Block.dropStack(world, where, new ItemStack(state.getBlock())); + } + else + { + if (how > 0) + tool.addEnchantment(Enchantments.FORTUNE, (int) how); + Block.dropStacks(state, world, where, be, null, tool); + } } - return (c_, t_) -> Value.TRUE; + if (!playerBreak) + return (c_, t_) -> Value.TRUE; + if (toolBroke) + return LazyValue.NULL; + Value ret = new NBTSerializableValue(tool.getTag()); + return (_c, _t) -> ret; + }); this.expr.addLazyFunction("harvest", -1, (c, t, lv) -> From c3137203b206b25c3135253526f761dc77f2fb74 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 6 Feb 2020 21:00:02 -0400 Subject: [PATCH 4/4] reworked destroy --- .../java/carpet/script/CarpetExpression.java | 90 +++++++++++++++---- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 218233cf..a579512b 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -44,6 +44,7 @@ import net.minecraft.block.JigsawBlock; import net.minecraft.block.StructureBlock; import net.minecraft.block.entity.BlockEntity; import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.FallingBlockEntity; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -154,6 +155,7 @@ public class CarpetExpression private final Expression expr; Expression getExpr() {return expr;} private static long tickStart = 0L; + private static FallingBlockEntity DUMMY_ENTITY = new FallingBlockEntity(EntityType.FALLING_BLOCK, null); private static boolean stopAll = false; @@ -521,9 +523,45 @@ public class CarpetExpression *

Causes a block to tick at position.

*

random_tick(pos)

*

Causes a random tick at position.

- *

destroy(pos), destroy(pos, -1), destroy(pos, <N>)

+ *

destroy(pos), destroy(pos, -1), destroy(pos, <N>), destroy(pos, tool, nbt?)

*

Destroys the block like it was mined by a player. Add -1 for silk touch, and positive number for fortune level. - * This function, unlike harvest, will affect all kinds of blocks

+ * If tool is specified, and optionally its nbt, it will use that tool and will attempt to mine the block with this tool. + * If called without item context, this function, unlike harvest, will affect all kinds of blocks. If called with item in context, + * it will fail to break blocks that cannot be broken by a survival player.

+ *

Without item context it returns false if failed to destroy the block and true if block breaking was + * successful. In item context, true means that breaking item has no nbt to use, null indicating that + * the tool should be considered broken in process, and nbt type value, for a resulting NBT tag on a hypothetical tool. + * Its up to the programmer to use that nbt to apply it where it belong + *

+ *

Here is a sample code that can be used to mine blocks using items in player inventory, without using player context for mining. + * Obviously, in this case the use of harvest would be much more applicable:

+ *
+     * mine(x,y,z) ->
+     * (
+     *    p = player();
+     *    slot = p~'selected_slot';
+     *    item_tuple = inventory_get(p, slot);
+     *    if (!item_tuple, destroy(x,y,z,'air'); return()); // empty hand, just break with 'air'
+     *    l(item, count, tag) = item_tuple;
+     *    tag_back = destroy(x,y,z, item, tag);
+     *    if (tag_back == false, // failed to break the item
+     * 	     return(tag_back)
+     *    );
+     *    if (tag_back == true, // block broke, tool has no tag
+     * 	     return(tag_back)
+     *    );
+     *    if (tag_back == null, //item broke
+     * 	     delete(tag:'Damage');
+     * 	     inventory_set(p, slot, count-1, item, tag);
+     * 	     return(tag_back)
+     *    );
+     *    if (type(tag_back) == 'nbt', // item didn't break, here is the effective nbt
+     * 	     inventory_set(p, slot, count, item, tag_back);
+     * 	     return(tag_back)
+     *    );
+     *    print('How did we get here?');
+     * )
+     * 
*

harvest(player, pos)

*

Causes a block to be harvested by a specified player entity. Honors player item enchantments, as well as damages the * tool if applicable. If the entity is not a valid player, no block gets destroyed. If a player is not allowed to @@ -1243,25 +1281,40 @@ public class CarpetExpression BlockPos where = locator.block.getPos(); BlockEntity be = world.getBlockEntity(where); long how = 0; - if (lv.size() > locator.offset) - how = NumericValue.asNumber(lv.get(locator.offset).evalValue(cc)).getLong(); Item item = Items.DIAMOND_PICKAXE; boolean playerBreak = false; - if (lv.size() > locator.offset+1) + if (lv.size() > locator.offset) { - playerBreak = true; - String itemString = lv.get(locator.offset+1).evalValue(c).getString(); - item = Registry.ITEM.get(new Identifier(itemString)); - if (item == Items.AIR && !itemString.equals("air")) throw new InternalExpressionException("Incorrect item: "+itemString); + Value val = lv.get(locator.offset).evalValue(c); + if (val instanceof NumericValue) + { + how = ((NumericValue) val).getLong(); + } + else + { + playerBreak = true; + String itemString = val.getString(); + item = Registry.ITEM.get(new Identifier(itemString)); + if (item == Items.AIR && !itemString.equals("air")) + throw new InternalExpressionException("Incorrect item: " + itemString); + } } CompoundTag tag = null; - if (lv.size() > locator.offset+2) + if (lv.size() > locator.offset+1) { - Value tagValue = lv.get(locator.offset+2).evalValue(c); - if (tagValue instanceof NBTSerializableValue) + if (!playerBreak) throw new InternalExpressionException("tag is not necessary with 'destroy' with no item"); + Value tagValue = lv.get(locator.offset+1).evalValue(c); + if (tagValue instanceof NullValue) + tag = null; + else if (tagValue instanceof NBTSerializableValue) tag = ((NBTSerializableValue) tagValue).getCompoundTag(); else - tag = NBTSerializableValue.parseString(tagValue.getString()).getCompoundTag(); + { + NBTSerializableValue readTag = NBTSerializableValue.parseString(tagValue.getString()); + if (readTag == null) + throw new InternalExpressionException("Incorrect tag: "+tagValue.getString()); + tag = readTag.getCompoundTag(); + } } ItemStack tool = new ItemStack(item, 1); @@ -1277,7 +1330,7 @@ public class CarpetExpression if (playerBreak) { boolean isUsingEffectiveTool = state.getMaterial().canBreakByHand() || tool.isEffectiveOn(state); - //postMine durability + //postMine() durability from item classes float hardness = state.getHardness(world, where); int damageAmount = 0; if ((item instanceof MiningToolItem && hardness > 0.0) || item instanceof ShearsItem) @@ -1303,14 +1356,17 @@ public class CarpetExpression { if (how > 0) tool.addEnchantment(Enchantments.FORTUNE, (int) how); - Block.dropStacks(state, world, where, be, null, tool); + Block.dropStacks(state, world, where, be, DUMMY_ENTITY, tool); } } - if (!playerBreak) + if (!playerBreak) // no tool info - block brokwn return (c_, t_) -> Value.TRUE; if (toolBroke) return LazyValue.NULL; - Value ret = new NBTSerializableValue(tool.getTag()); + Tag outtag = tool.getTag(); + if (outtag == null) + return LazyValue.TRUE; + Value ret = new NBTSerializableValue(outtag); return (_c, _t) -> ret; });