From d4376dd387b320d9c343740f631e03006ee100cd Mon Sep 17 00:00:00 2001 From: Dioswilson Date: Tue, 17 May 2022 16:23:32 -0300 Subject: [PATCH] Updated carpet to last version except from Redstone Multimeter because im lazy AF --- carpetmodSrc/carpet/CarpetSettings.java | 5 +- .../carpet/commands/CarpetCommands.java | 2 + .../carpet/commands/CommandColon.java | 318 ++++++++++++++++++ carpetmodSrc/carpet/commands/CommandFeel.java | 270 +++++++++++++++ .../carpet/commands/CommandZetBlock.java | 15 +- .../carpet/helpers/SaveSavestatesHelper.java | 63 ++++ .../carpet/prometheus/MetricUpdater.java | 2 +- docs/usage/install.rst | 2 +- mktest.sh | 2 +- .../minecraft/command/CommandFill.java.patch | 36 +- .../inventory/ItemStackHelper.java.patch | 25 ++ 11 files changed, 717 insertions(+), 23 deletions(-) create mode 100644 carpetmodSrc/carpet/commands/CommandColon.java create mode 100644 carpetmodSrc/carpet/commands/CommandFeel.java create mode 100644 carpetmodSrc/carpet/helpers/SaveSavestatesHelper.java create mode 100644 patches/net/minecraft/inventory/ItemStackHelper.java.patch diff --git a/carpetmodSrc/carpet/CarpetSettings.java b/carpetmodSrc/carpet/CarpetSettings.java index d6a1e52..843facc 100644 --- a/carpetmodSrc/carpet/CarpetSettings.java +++ b/carpetmodSrc/carpet/CarpetSettings.java @@ -44,7 +44,7 @@ public class CarpetSettings { public static boolean locked = false; - public static final String carpetVersion = "v22_02_09"; + public static final String carpetVersion = "v22_3_21"; public static final String minecraftVersion = "1.12.2"; public static final String mcpMappings = "39-1.12"; @@ -820,6 +820,9 @@ private static boolean validateRandomTickOptimization(boolean value) { @Rule(desc = "Sends invisible duplicate UUID entities to clients", category = FIX) public static boolean sendDuplicateEntitiesToClients = false; + @Rule(desc = "Enables best-effort saving of savestated chunks", category = FIX) + public static boolean saveSavestates = false; + // ===== FEATURES ===== // @Rule(desc = "Enables skyblock on 1.12, all blocks but end portal frames will be removed in newly generated chunks.", category = FEATURE, extra = "WARNING! Don't turn on if not planning to play skyblock.") diff --git a/carpetmodSrc/carpet/commands/CarpetCommands.java b/carpetmodSrc/carpet/commands/CarpetCommands.java index 3ab99d6..c292ec4 100644 --- a/carpetmodSrc/carpet/commands/CarpetCommands.java +++ b/carpetmodSrc/carpet/commands/CarpetCommands.java @@ -11,12 +11,14 @@ public static void register(CommandHandler handler) { handler.registerCommand(new CommandBlockInfo()); handler.registerCommand(new CommandCarpet()); handler.registerCommand(new CommandChunk()); + handler.registerCommand(new CommandColon()); handler.registerCommand(new CommandCounter()); handler.registerCommand(new CommandDebugCarpet()); handler.registerCommand(new CommandDebuglogger()); handler.registerCommand(new CommandDistance()); handler.registerCommand(new CommandEnderchest());//Bullet handler.registerCommand(new CommandEntityInfo()); + handler.registerCommand(new CommandFeel()); handler.registerCommand(new CommandFillBiome()); handler.registerCommand(new CommandGMC()); handler.registerCommand(new CommandGMS()); diff --git a/carpetmodSrc/carpet/commands/CommandColon.java b/carpetmodSrc/carpet/commands/CommandColon.java new file mode 100644 index 0000000..b88a29b --- /dev/null +++ b/carpetmodSrc/carpet/commands/CommandColon.java @@ -0,0 +1,318 @@ +package carpet.commands; + +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; +import java.util.Collections; +import java.util.Deque; +import java.util.List; +import javax.annotation.Nullable; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandClone; +import net.minecraft.command.CommandException; +import net.minecraft.command.CommandResultStats; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.NextTickListEntry; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.StructureBoundingBox; + +import carpet.CarpetSettings; +import carpet.worldedit.WorldEditBridge; +import net.minecraft.entity.player.EntityPlayerMP; + +public class CommandColon extends CommandBase +{ + /** + * Gets the name of the command + */ + public String getName() + { + return "colon"; + } + + /** + * Return the required permission level for this command. + */ + public int getRequiredPermissionLevel() + { + return 2; + } + + /** + * Gets the usage string for the command. + */ + public String getUsage(ICommandSender sender) + { + return "commands.clone.usage"; + } + + /** + * Callback for when the command is executed + */ + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException + { + if (args.length < 9) + { + throw new WrongUsageException("commands.clone.usage", new Object[0]); + } + else + { + sender.setCommandStat(CommandResultStats.Type.AFFECTED_BLOCKS, 0); + BlockPos blockpos = parseBlockPos(sender, args, 0, false); + BlockPos blockpos1 = parseBlockPos(sender, args, 3, false); + BlockPos blockpos2 = parseBlockPos(sender, args, 6, false); + StructureBoundingBox structureboundingbox = new StructureBoundingBox(blockpos, blockpos1); + StructureBoundingBox structureboundingbox1 = new StructureBoundingBox(blockpos2, blockpos2.add(structureboundingbox.getLength())); + + boolean flag = false; + Block block = null; + Predicate predicate = null; + + if ((args.length < 11 || !"force".equals(args[10]) && !"move".equals(args[10]) && !"force_noupdate".equals(args[10]) && !"move_noupdate".equals(args[10])) && structureboundingbox.intersectsWith(structureboundingbox1)) + { + throw new CommandException("commands.clone.noOverlap", new Object[0]); + } + else + { + if (args.length >= 11 && ("move".equals(args[10]) || "move_noupdate".equals(args[10]))) + { + flag = true; + } + + boolean update = true; + if (args.length >= 11 && ("noupdate".equals(args[10]) || "force_noupdate".equals(args[10]) || "move_noupdate".equals(args[10]))) + { + update = false; + } + + if (structureboundingbox.minY >= 0 && structureboundingbox.maxY < 256 && structureboundingbox1.minY >= 0 && structureboundingbox1.maxY < 256) + { + World world = sender.getEntityWorld(); + + boolean flag1 = false; + + if (args.length >= 10) + { + if ("masked".equals(args[9])) + { + flag1 = true; + } + else if ("filtered".equals(args[9])) + { + if (args.length < 12) + { + throw new WrongUsageException("commands.clone.usage", new Object[0]); + } + + block = getBlockByText(sender, args[11]); + + if (args.length >= 13) + { + predicate = convertArgToBlockStatePredicate(block, args[12]); + } + } + } + + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); + List list2 = Lists.newArrayList(); + Deque deque = Lists.newLinkedList(); + BlockPos blockpos3 = new BlockPos(structureboundingbox1.minX - structureboundingbox.minX, structureboundingbox1.minY - structureboundingbox.minY, structureboundingbox1.minZ - structureboundingbox.minZ); + + for (int j = structureboundingbox.minZ; j <= structureboundingbox.maxZ; ++j) + { + for (int k = structureboundingbox.minY; k <= structureboundingbox.maxY; ++k) + { + for (int l = structureboundingbox.minX; l <= structureboundingbox.maxX; ++l) + { + BlockPos blockpos4 = new BlockPos(l, k, j); + BlockPos blockpos5 = blockpos4.add(blockpos3); + IBlockState iblockstate = world.getBlockState(blockpos4); + + if ((!flag1 || iblockstate.getBlock() != Blocks.AIR) && (block == null || iblockstate.getBlock() == block && (predicate == null || predicate.apply(iblockstate)))) + { + TileEntity tileentity = world.getTileEntity(blockpos4); + + if (tileentity != null) + { + NBTTagCompound nbttagcompound = tileentity.writeToNBT(new NBTTagCompound()); + list1.add(new StaticCloneData(blockpos5, iblockstate, nbttagcompound)); + deque.addLast(blockpos4); + } + else if (!iblockstate.isFullBlock() && !iblockstate.isFullCube()) + { + list2.add(new StaticCloneData(blockpos5, iblockstate, (NBTTagCompound)null)); + deque.addFirst(blockpos4); + } + else + { + list.add(new StaticCloneData(blockpos5, iblockstate, (NBTTagCompound)null)); + deque.addLast(blockpos4); + } + } + } + } + } + + EntityPlayerMP worldEditPlayer = sender instanceof EntityPlayerMP ? (EntityPlayerMP) sender : null; + + if (flag) + { + for (BlockPos blockpos6 : deque) + { + WorldEditBridge.recordBlockEdit(worldEditPlayer, world, blockpos6, Blocks.AIR.getDefaultState(), null); + TileEntity tileentity1 = world.getTileEntity(blockpos6); + + if (tileentity1 instanceof IInventory) + { + ((IInventory)tileentity1).clear(); + } + + world.setBlockState(blockpos6, Blocks.BARRIER.getDefaultState(), 2 | (update?0:128)); //carpet + } + + for (BlockPos blockpos7 : deque) + { + world.setBlockState(blockpos7, Blocks.AIR.getDefaultState(), (update?3:131)); //carpet + } + } + + List list3 = Lists.newArrayList(); + list3.addAll(list); + list3.addAll(list1); + list3.addAll(list2); + List list4 = Lists.reverse(list3); + + for (StaticCloneData commandclone$staticclonedata : list4) + { + WorldEditBridge.recordBlockEdit(worldEditPlayer, world, commandclone$staticclonedata.pos, commandclone$staticclonedata.blockState, commandclone$staticclonedata.nbt); + TileEntity tileentity2 = world.getTileEntity(commandclone$staticclonedata.pos); + + if (tileentity2 instanceof IInventory) + { + ((IInventory)tileentity2).clear(); + } + + world.setBlockState(commandclone$staticclonedata.pos, Blocks.BARRIER.getDefaultState(), 2 | (update?0:128)); //carpet + } + + int i = 0; + + for (StaticCloneData commandclone$staticclonedata1 : list3) + { + if (world.setBlockState(commandclone$staticclonedata1.pos, commandclone$staticclonedata1.blockState, 2 | (update?0:128))) //carpet + { + ++i; + } + } + for (StaticCloneData commandclone$staticclonedata2 : list1) + { + TileEntity tileentity3 = world.getTileEntity(commandclone$staticclonedata2.pos); + + if (commandclone$staticclonedata2.nbt != null && tileentity3 != null) + { + commandclone$staticclonedata2.nbt.setInteger("x", commandclone$staticclonedata2.pos.getX()); + commandclone$staticclonedata2.nbt.setInteger("y", commandclone$staticclonedata2.pos.getY()); + commandclone$staticclonedata2.nbt.setInteger("z", commandclone$staticclonedata2.pos.getZ()); + tileentity3.readFromNBT(commandclone$staticclonedata2.nbt); + tileentity3.markDirty(); + } + + world.setBlockState(commandclone$staticclonedata2.pos, commandclone$staticclonedata2.blockState, 2); + } + + /*carpet mod */ + if (update) + { + /*carpet mod end EXTRA INDENTATION START*/ + for (StaticCloneData commandclone$staticclonedata3 : list4) + { + world.notifyNeighborsRespectDebug(commandclone$staticclonedata3.pos, commandclone$staticclonedata3.blockState.getBlock(), false); + } + + List list5 = world.getPendingBlockUpdates(structureboundingbox, false); + + if (list5 != null) + { + for (NextTickListEntry nextticklistentry : list5) + { + if (structureboundingbox.isVecInside(nextticklistentry.position)) + { + BlockPos blockpos8 = nextticklistentry.position.add(blockpos3); + world.scheduleBlockUpdate(blockpos8, nextticklistentry.getBlock(), (int)(nextticklistentry.scheduledTime - world.getWorldInfo().getWorldTotalTime()), nextticklistentry.priority); + } + } + } + } //carpet mod back extra indentation + + if (i <= 0) + { + throw new CommandException("commands.clone.failed", new Object[0]); + } + else + { + sender.setCommandStat(CommandResultStats.Type.AFFECTED_BLOCKS, i); + notifyCommandListener(sender, this, "commands.clone.success", new Object[] {i}); + } + } + else + { + throw new CommandException("commands.clone.outOfWorld", new Object[0]); + } + } + } + } + + /** + * Get a list of options for when the user presses the TAB key + */ + public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) + { + if (args.length > 0 && args.length <= 3) + { + return getTabCompletionCoordinate(args, 0, targetPos); + } + else if (args.length > 3 && args.length <= 6) + { + return getTabCompletionCoordinate(args, 3, targetPos); + } + else if (args.length > 6 && args.length <= 9) + { + return getTabCompletionCoordinate(args, 6, targetPos); + } + else if (args.length == 10) + { + return getListOfStringsMatchingLastWord(args, new String[] {"replace", "masked", "filtered"}); + } + else if (args.length == 11) + { + return getListOfStringsMatchingLastWord(args, new String[] {"normal", "force", "move", "noupdate", "force_noupdate", "move_noupdate"}); + } + else + { + return args.length == 12 && "filtered".equals(args[9]) ? getListOfStringsMatchingLastWord(args, Block.REGISTRY.getKeys()) : Collections.emptyList(); + } + } + + static class StaticCloneData + { + public final BlockPos pos; + public final IBlockState blockState; + public final NBTTagCompound nbt; + + public StaticCloneData(BlockPos posIn, IBlockState stateIn, NBTTagCompound compoundIn) + { + this.pos = posIn; + this.blockState = stateIn; + this.nbt = compoundIn; + } + } +} diff --git a/carpetmodSrc/carpet/commands/CommandFeel.java b/carpetmodSrc/carpet/commands/CommandFeel.java new file mode 100644 index 0000000..e3e87d9 --- /dev/null +++ b/carpetmodSrc/carpet/commands/CommandFeel.java @@ -0,0 +1,270 @@ +package carpet.commands; + +import com.google.common.collect.Lists; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.function.Predicate; +import javax.annotation.Nullable; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.CommandResultStats; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.NBTException; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import carpet.CarpetSettings; +import carpet.helpers.CapturedDrops; +import carpet.worldedit.WorldEditBridge; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayerMP; + +public class CommandFeel extends CommandBase +{ + /** + * Gets the name of the command + */ + public String getName() + { + return "feel"; + } + + /** + * Return the required permission level for this command. + */ + public int getRequiredPermissionLevel() + { + return 2; + } + + /** + * Gets the usage string for the command. + */ + public String getUsage(ICommandSender sender) + { + return "commands.fill.usage"; + } + + /** + * Callback for when the command is executed + */ + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException + { + if (args.length < 7) + { + throw new WrongUsageException("commands.fill.usage", new Object[0]); + } + else + { + sender.setCommandStat(CommandResultStats.Type.AFFECTED_BLOCKS, 0); + BlockPos blockpos = parseBlockPos(sender, args, 0, false); + BlockPos blockpos1 = parseBlockPos(sender, args, 3, false); + Block block = CommandBase.getBlockByText(sender, args[6]); + IBlockState iblockstate; + + if (args.length >= 8) + { + iblockstate = convertArgToBlockState(block, args[7]); + } + else + { + iblockstate = block.getDefaultState(); + } + + BlockPos blockpos2 = new BlockPos(Math.min(blockpos.getX(), blockpos1.getX()), Math.min(blockpos.getY(), blockpos1.getY()), Math.min(blockpos.getZ(), blockpos1.getZ())); + BlockPos blockpos3 = new BlockPos(Math.max(blockpos.getX(), blockpos1.getX()), Math.max(blockpos.getY(), blockpos1.getY()), Math.max(blockpos.getZ(), blockpos1.getZ())); + int i = (blockpos3.getX() - blockpos2.getX() + 1) * (blockpos3.getY() - blockpos2.getY() + 1) * (blockpos3.getZ() - blockpos2.getZ() + 1); + + if (blockpos2.getY() >= 0 && blockpos3.getY() < 256) + { + World world = sender.getEntityWorld(); + + NBTTagCompound nbttagcompound = new NBTTagCompound(); + boolean flag = false; + + if (args.length >= 10 && block.hasTileEntity()) + { + String s = buildString(args, 9); + + try + { + nbttagcompound = JsonToNBT.getTagFromJson(s); + flag = true; + } + catch (NBTException nbtexception) + { + throw new CommandException("commands.fill.tagError", new Object[] {nbtexception.getMessage()}); + } + } + + FillType mode; + try { + mode = args.length <= 8 ? FillType.REPLACE : FillType.valueOf(args[8].toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException e) { + mode = FillType.REPLACE; + } + Block toReplace = null; + Predicate toReplacePredicate = state -> true; + if ((mode == FillType.REPLACE || mode == FillType.NOUPDATE) && args.length > 9) { + toReplace = CommandBase.getBlockByText(sender, args[9]); + if (args.length > 10 && !args[10].equals("-1") && !args[10].equals("*")) { + toReplacePredicate = CommandBase.convertArgToBlockStatePredicate(toReplace, args[10]); + } + } + + EntityPlayerMP worldEditPlayer = sender instanceof EntityPlayerMP ? (EntityPlayerMP) sender : null; + NBTTagCompound worldEditTag = flag ? nbttagcompound : null; + + List list = Lists.newArrayList(); + i = 0; + + for (int l = blockpos2.getZ(); l <= blockpos3.getZ(); ++l) + { + for (int i1 = blockpos2.getY(); i1 <= blockpos3.getY(); ++i1) + { + for (int j1 = blockpos2.getX(); j1 <= blockpos3.getX(); ++j1) + { + BlockPos blockpos4 = new BlockPos(j1, i1, l); + + if (args.length >= 9) + { + if (mode != FillType.OUTLINE && mode != FillType.HOLLOW) + { + if (mode == FillType.DESTROY) + { + WorldEditBridge.recordBlockEdit(worldEditPlayer, world, blockpos4, Blocks.AIR.getDefaultState(), worldEditTag); + CapturedDrops.setCapturingDrops(true); + world.destroyBlock(blockpos4, true); + CapturedDrops.setCapturingDrops(false); + for (EntityItem drop : CapturedDrops.getCapturedDrops()) + WorldEditBridge.recordEntityCreation(worldEditPlayer, world, drop); + CapturedDrops.clearCapturedDrops(); + } + else if (mode == FillType.KEEP) + { + if (!world.isAirBlock(blockpos4)) + { + continue; + } + } + else if ((mode == FillType.REPLACE || mode == FillType.NOUPDATE) && !block.hasTileEntity() && args.length > 9) + { + IBlockState state = world.getBlockState(blockpos4); + if (state.getBlock() != toReplace || !toReplacePredicate.test(state)) + { + continue; + } + } + } + else if (j1 != blockpos2.getX() && j1 != blockpos3.getX() && i1 != blockpos2.getY() && i1 != blockpos3.getY() && l != blockpos2.getZ() && l != blockpos3.getZ()) + { + if (mode == FillType.HOLLOW) + { + WorldEditBridge.recordBlockEdit(worldEditPlayer, world, blockpos4, Blocks.AIR.getDefaultState(), worldEditTag); + world.setBlockState(blockpos4, Blocks.AIR.getDefaultState(), 2); + list.add(blockpos4); + } + + continue; + } + } + + WorldEditBridge.recordBlockEdit(worldEditPlayer, world, blockpos4, iblockstate, worldEditTag); + TileEntity tileentity1 = world.getTileEntity(blockpos4); + + if (tileentity1 != null && tileentity1 instanceof IInventory) + { + ((IInventory)tileentity1).clear(); + } + + if (world.setBlockState(blockpos4, iblockstate, 2 | (mode != FillType.NOUPDATE?0:128) )) //CM + { + list.add(blockpos4); + ++i; + + if (flag) + { + TileEntity tileentity = world.getTileEntity(blockpos4); + + if (tileentity != null) + { + nbttagcompound.setInteger("x", blockpos4.getX()); + nbttagcompound.setInteger("y", blockpos4.getY()); + nbttagcompound.setInteger("z", blockpos4.getZ()); + tileentity.readFromNBT(nbttagcompound); + } + } + } + } + } + } + + /*carpet mod */ + if (mode != FillType.NOUPDATE) + { + /*carpet mod end EXTRA INDENT*/ + for (BlockPos blockpos5 : list) + { + Block block2 = world.getBlockState(blockpos5).getBlock(); + world.notifyNeighborsRespectDebug(blockpos5, block2, false); + } + } //carpet mod back extra indentation + + if (i <= 0) + { + throw new CommandException("commands.fill.failed", new Object[0]); + } + else + { + sender.setCommandStat(CommandResultStats.Type.AFFECTED_BLOCKS, i); + notifyCommandListener(sender, this, "commands.fill.success", new Object[] {i}); + } + } + else + { + throw new CommandException("commands.fill.outOfWorld", new Object[0]); + } + } + } + + /** + * Get a list of options for when the user presses the TAB key + */ + public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) + { + if (args.length > 0 && args.length <= 3) + { + return getTabCompletionCoordinate(args, 0, targetPos); + } + else if (args.length > 3 && args.length <= 6) + { + return getTabCompletionCoordinate(args, 3, targetPos); + } + else if (args.length == 7) + { + return getListOfStringsMatchingLastWord(args, Block.REGISTRY.getKeys()); + } + else if (args.length == 9) + { + return getListOfStringsMatchingLastWord(args, new String[] {"replace", "destroy", "keep", "hollow", "outline", "noupdate", "replace_noupdate"}); + } + else + { + return args.length == 10 && ("replace".equalsIgnoreCase(args[8]) || "noupdate".equalsIgnoreCase(args[8])) ? getListOfStringsMatchingLastWord(args, Block.REGISTRY.getKeys()) : Collections.emptyList(); + } + } + + enum FillType { + REPLACE, DESTROY, KEEP, HOLLOW, OUTLINE, NOUPDATE; + } +} diff --git a/carpetmodSrc/carpet/commands/CommandZetBlock.java b/carpetmodSrc/carpet/commands/CommandZetBlock.java index b1474e6..7fd2765 100644 --- a/carpetmodSrc/carpet/commands/CommandZetBlock.java +++ b/carpetmodSrc/carpet/commands/CommandZetBlock.java @@ -96,6 +96,8 @@ public void execute(MinecraftServer server, ICommandSender sender, String[] args EntityPlayerMP worldEditPlayer = sender instanceof EntityPlayerMP ? (EntityPlayerMP) sender : null; NBTTagCompound worldEditTag = flag ? nbttagcompound : null; + boolean updates = true; + if (args.length >= 6) { if ("destroy".equals(args[5])) @@ -118,6 +120,10 @@ else if ("keep".equals(args[5]) && !world.isAirBlock(blockpos)) { throw new CommandException("commands.setblock.noChange", new Object[0]); } + else if ("noupdate".equals(args[5])) + { + updates = false; + } } WorldEditBridge.recordBlockEdit(worldEditPlayer, world, blockpos, iblockstate, worldEditTag); @@ -129,7 +135,7 @@ else if ("keep".equals(args[5]) && !world.isAirBlock(blockpos)) ((IInventory)tileentity1).clear(); } - if (!world.setBlockState(blockpos, iblockstate, 2)) + if (!world.setBlockState(blockpos, iblockstate, 2 | (updates ? 0 : 128))) { throw new CommandException("commands.setblock.noChange", new Object[0]); } @@ -148,7 +154,10 @@ else if ("keep".equals(args[5]) && !world.isAirBlock(blockpos)) } } - world.notifyNeighborsRespectDebug(blockpos, iblockstate.getBlock(), false); + if (updates) + { + world.notifyNeighborsRespectDebug(blockpos, iblockstate.getBlock(), false); + } sender.setCommandStat(CommandResultStats.Type.AFFECTED_BLOCKS, 1); notifyCommandListener(sender, this, "commands.setblock.success", new Object[0]); } @@ -170,7 +179,7 @@ else if (args.length == 4) } else { - return args.length == 6 ? getListOfStringsMatchingLastWord(args, new String[] {"replace", "destroy", "keep"}) : Collections.emptyList(); + return args.length == 6 ? getListOfStringsMatchingLastWord(args, new String[] {"replace", "destroy", "keep", "noupdate"}) : Collections.emptyList(); } } } diff --git a/carpetmodSrc/carpet/helpers/SaveSavestatesHelper.java b/carpetmodSrc/carpet/helpers/SaveSavestatesHelper.java new file mode 100644 index 0000000..1109b02 --- /dev/null +++ b/carpetmodSrc/carpet/helpers/SaveSavestatesHelper.java @@ -0,0 +1,63 @@ +package carpet.helpers; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.NonNullList; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.List; + +public class SaveSavestatesHelper { + public static void trySaveItemsCompressed(NBTTagCompound destTag, NonNullList items, boolean saveEmpty) { + List> itemsAndSlots = new ArrayList<>(items.size()); + for (int i = 0; i < items.size(); i++) { + itemsAndSlots.add(Pair.of(i, items.get(i))); + } + + itemsAndSlots.sort((a, b) -> compareItems(a.getRight(), b.getRight())); + + NBTTagList itemsTag = new NBTTagList(); + for (Pair itemAndSlot : itemsAndSlots) { + int slot = itemAndSlot.getLeft(); + ItemStack item = itemAndSlot.getRight(); + if (!item.isEmpty()) { + NBTTagCompound itemTag = new NBTTagCompound(); + itemTag.setByte("Slot", (byte) slot); + item.writeToNBT(itemTag); + itemsTag.appendTag(itemTag); + } + } + + if (!itemsTag.isEmpty() || saveEmpty) { + destTag.setTag("Items", itemsTag); + } + } + + private static int compareItems(ItemStack a, ItemStack b) { + int idA = Item.getIdFromItem(a.getItem()); + int idB = Item.getIdFromItem(b.getItem()); + if (idA != idB) { + return Integer.compare(idA, idB); + } + + NBTTagCompound tagA = a.getTagCompound(); + NBTTagCompound tagB = b.getTagCompound(); + if (tagA != null && tagB != null) { + NBTTagList pagesA = tagA.getTagList("pages", 8); + NBTTagList pagesB = tagB.getTagList("pages", 8); + for (int page = 0; page < Math.min(pagesA.tagCount(), pagesB.tagCount()); page++) { + String pageA = pagesA.getStringTagAt(page); + String pageB = pagesB.getStringTagAt(page); + int cmp = pageA.compareTo(pageB); + if (cmp != 0) { + return cmp; + } + } + } + + return 0; + } +} diff --git a/carpetmodSrc/carpet/prometheus/MetricUpdater.java b/carpetmodSrc/carpet/prometheus/MetricUpdater.java index 3353a54..28a7fd9 100644 --- a/carpetmodSrc/carpet/prometheus/MetricUpdater.java +++ b/carpetmodSrc/carpet/prometheus/MetricUpdater.java @@ -22,7 +22,7 @@ public void run() { try { metric.update(this.extension); } catch (Exception exception) { - exception.printStackTrace(); + //exception.printStackTrace(); } } } diff --git a/docs/usage/install.rst b/docs/usage/install.rst index ad148c2..ae19513 100644 --- a/docs/usage/install.rst +++ b/docs/usage/install.rst @@ -35,7 +35,7 @@ First, create a clean directory (folder). For this tutorial, we call it ``carpet``. There, download the vanilla jar and Carpet patch. * `Download the 1.12.2 vanilla server jar - `_. + `_. * `Download the latest Carpet patch `_. diff --git a/mktest.sh b/mktest.sh index 8beb25e..ca3ca14 100644 --- a/mktest.sh +++ b/mktest.sh @@ -69,7 +69,7 @@ else cp "$GRADLE_CACHE_JAR" "$MC_JAR" else echo "Downloading server ..." - wget "https://s3.amazonaws.com/Minecraft.Download/versions/1.12.2/minecraft_server.1.12.2.jar" -O "$MC_JAR" || { echo "failed to download MC jar" && exit 1; } + wget "https://launcher.mojang.com/v1/objects/886945bfb2b978778c3a0288fd7fab09d315b25f/server.jar" -O "$MC_JAR" || { echo "failed to download MC jar" && exit 1; } cp "$MC_JAR" "$MC_JAR.orig" fi fi diff --git a/patches/net/minecraft/command/CommandFill.java.patch b/patches/net/minecraft/command/CommandFill.java.patch index dcb35dc..d415356 100644 --- a/patches/net/minecraft/command/CommandFill.java.patch +++ b/patches/net/minecraft/command/CommandFill.java.patch @@ -25,16 +25,16 @@ } else if (blockpos2.func_177956_o() >= 0 && blockpos3.func_177956_o() < 256) { -@@ -96,6 +102,9 @@ - throw new CommandException("commands.fill.tagError", new Object[] {nbtexception.getMessage()}); +@@ -97,6 +103,9 @@ } } -+ + + EntityPlayerMP worldEditPlayer = p_184881_2_ instanceof EntityPlayerMP ? (EntityPlayerMP) p_184881_2_ : null; + NBTTagCompound worldEditTag = flag ? nbttagcompound : null; - ++ List list = Lists.newArrayList(); i = 0; + @@ -114,7 +123,13 @@ { if ("destroy".equals(p_184881_3_[8])) @@ -49,14 +49,16 @@ } else if ("keep".equals(p_184881_3_[8])) { -@@ -137,6 +152,7 @@ +@@ -137,7 +152,8 @@ { if ("hollow".equals(p_184881_3_[8])) { +- world.func_180501_a(blockpos4, Blocks.field_150350_a.func_176223_P(), 2); + WorldEditBridge.recordBlockEdit(worldEditPlayer, world, blockpos4, Blocks.field_150350_a.func_176223_P(), worldEditTag); - world.func_180501_a(blockpos4, Blocks.field_150350_a.func_176223_P(), 2); ++ world.func_180501_a(blockpos4, Blocks.field_150350_a.func_176223_P(), 2 | (CarpetSettings.fillUpdates?0:128)); // CM list.add(blockpos4); } + @@ -145,6 +161,7 @@ } } @@ -74,21 +76,23 @@ { list.add(blockpos4); ++i; -@@ -173,12 +190,17 @@ - } +@@ -174,11 +191,16 @@ } } -- -+ + +- for (BlockPos blockpos5 : list) + /*carpet mod */ + if (CarpetSettings.fillUpdates) -+ { -+ /*carpet mod end EXTRA INDENT*/ - for (BlockPos blockpos5 : list) { - Block block2 = world.func_180495_p(blockpos5).func_177230_c(); - world.func_175722_b(blockpos5, block2, false); - } +- Block block2 = world.func_180495_p(blockpos5).func_177230_c(); +- world.func_175722_b(blockpos5, block2, false); +- } ++ /*carpet mod end EXTRA INDENT*/ ++ for (BlockPos blockpos5 : list) ++ { ++ Block block2 = world.func_180495_p(blockpos5).func_177230_c(); ++ world.func_175722_b(blockpos5, block2, false); ++ } + } //carpet mod back extra indentation if (i <= 0) diff --git a/patches/net/minecraft/inventory/ItemStackHelper.java.patch b/patches/net/minecraft/inventory/ItemStackHelper.java.patch new file mode 100644 index 0000000..31bb7f6 --- /dev/null +++ b/patches/net/minecraft/inventory/ItemStackHelper.java.patch @@ -0,0 +1,25 @@ +--- ../src-base/minecraft/net/minecraft/inventory/ItemStackHelper.java ++++ ../src-work/minecraft/net/minecraft/inventory/ItemStackHelper.java +@@ -6,6 +6,9 @@ + import net.minecraft.nbt.NBTTagList; + import net.minecraft.util.NonNullList; + ++import carpet.CarpetSettings; ++import carpet.helpers.SaveSavestatesHelper; ++ + public class ItemStackHelper + { + public static ItemStack func_188382_a(List p_188382_0_, int p_188382_1_, int p_188382_2_) +@@ -25,6 +28,12 @@ + + public static NBTTagCompound func_191281_a(NBTTagCompound p_191281_0_, NonNullList p_191281_1_, boolean p_191281_2_) + { ++ if (CarpetSettings.saveSavestates) ++ { ++ SaveSavestatesHelper.trySaveItemsCompressed(p_191281_0_, p_191281_1_, p_191281_2_); ++ return p_191281_0_; ++ } ++ + NBTTagList nbttaglist = new NBTTagList(); + + for (int i = 0; i < p_191281_1_.size(); ++i)