diff --git a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java index 1d5c84f87..658689a45 100644 --- a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java +++ b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocalMultiplayer.java @@ -15,7 +15,6 @@ import net.minecraft.core.net.packet.PacketPlayerConfig; import net.minecraft.core.net.packet.PacketUpdatePlayerState; import net.minecraft.core.net.packet.PacketMovePlayer; import net.minecraft.core.net.packet.PacketContainerClose; -import net.minecraft.core.net.packet.PacketUpdateCreativeInventory; import net.minecraft.core.net.packet.PacketSetHotbarOffset; import net.minecraft.core.net.packet.PacketGuidebook; import net.minecraft.core.net.packet.PacketPlayerAction; @@ -172,12 +171,6 @@ public class PlayerLocalMultiplayer extends PlayerLocal implements Player.Player addToSendHistory(s); } - @Override - public void updateCreativeInventory(int page, String searchText) - { - sendQueue.addToSendQueue(new PacketUpdateCreativeInventory(containerMenu.containerId, page, searchText)); - } - @Override public void setHotbarOffset(int offset) { diff --git a/game/client/src/main/java/net/minecraft/client/gui/IntegerSliderElement.java b/game/client/src/main/java/net/minecraft/client/gui/IntegerSliderElement.java index db32b7bfc..950bb3256 100644 --- a/game/client/src/main/java/net/minecraft/client/gui/IntegerSliderElement.java +++ b/game/client/src/main/java/net/minecraft/client/gui/IntegerSliderElement.java @@ -1,5 +1,7 @@ package net.minecraft.client.gui; +import net.minecraft.client.option.Option; +import net.minecraft.client.option.OptionRange; import net.minecraft.client.render.renderer.GLRenderer; import net.minecraft.client.render.texture.stitcher.IconCoordinate; import net.minecraft.client.render.texture.stitcher.TextureRegistry; @@ -41,6 +43,14 @@ public class IntegerSliderElement extends ButtonElement { return 8; } + private int getStep() { + if(option instanceof OptionRange range) { + return range.step; + } + + return 1; + } + @Override public void mouseDragged(Minecraft mc, int mouseX, int mouseY) { if (!this.visible) { @@ -51,11 +61,15 @@ public class IntegerSliderElement extends ButtonElement { if (this.dragging) { int segments = maxValue; float percentage = (float) (mouseX - (this.xPosition + 4) - (this.width / (2 * segments))) / (float) (this.width - sliderWidth); + if (percentage > 1.0f) percentage = 1.0f; if (percentage < 0.0f) percentage = 0.0f; - this.sliderValue = (int) Math.ceil(segments * percentage); + + int step = this.getStep(); + + this.sliderValue = Math.round((segments * percentage) / (float) step) * step; this.option.setValueWithIndex(this.sliderValue); this.displayString = this.option.getDisplayStringValue(); } @@ -107,7 +121,10 @@ public class IntegerSliderElement extends ButtonElement { percentage = 1.0f; if (percentage < 0.0f) percentage = 0.0f; - this.sliderValue = (int) Math.ceil(segments * percentage); + + int step = this.getStep(); + + this.sliderValue = Math.round((segments * percentage) / (float) step) * step; this.option.setValueWithIndex(this.sliderValue); this.displayString = this.option.getDisplayStringValue(); this.dragging = true; diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java index 883fa65f7..7fe5970c6 100644 --- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java +++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenContainerAbstract.java @@ -248,40 +248,41 @@ public abstract class ScreenContainerAbstract extends Screen { cancelClick = true; } // Horrifying + // Still Horrifying... if (GameSettings.KEY_HOT_BAR_SLOT_1.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 1}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 1), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_2.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 2}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 2), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_3.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 3}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 3), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_4.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 4}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 4), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_5.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 5}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 5), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_6.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 6}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 6), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_7.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 7}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 7), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_8.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 8}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 8), this.mc.thePlayer); cancelClick = true; } if (GameSettings.KEY_HOT_BAR_SLOT_9.isKeyOrMouse(key, mouseButton)) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, new int[]{slotId, 9}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.HOTBAR_ITEM_SWAP, hotbarSwapArgs(slotId, 9), this.mc.thePlayer); cancelClick = true; } @@ -339,6 +340,19 @@ public abstract class ScreenContainerAbstract extends Screen { super.mouseReleased(mx, my, buttonNum); } + protected int[] creativeSlotArgs(Slot slot, int amount) { + ItemStack stack = slot.getItemStack(); + return new int[]{slot.index, amount, stack != null ? stack.itemID : 0, stack != null ? stack.getMetadata() : 0}; + } + + protected int[] hotbarSwapArgs(int slotId, int hotbarSlotNumber) { + Slot slot = this.inventorySlots.getSlot(slotId); + if (slot instanceof SlotCreative) { + return creativeSlotArgs(slot, hotbarSlotNumber); + } + return new int[]{slotId, hotbarSlotNumber}; + } + /** * This method controls what InventoryAction is sent to the server */ @@ -441,20 +455,20 @@ public abstract class ScreenContainerAbstract extends Screen { if (heldItem != null) { if (heldItem.canStackWith(stackInSlot)) { if (shiftPressed || ctrlPressed) { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, new int[]{slot.index, heldItem.getMaxStackSize()}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, creativeSlotArgs(slot, heldItem.getMaxStackSize()), this.mc.thePlayer); } else { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, new int[]{slot.index, heldItem.stackSize + 1}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, creativeSlotArgs(slot, heldItem.stackSize + 1), this.mc.thePlayer); } } else { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, new int[]{slot.index, 0}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, creativeSlotArgs(slot, 0), this.mc.thePlayer); } } else { if (shiftPressed || ctrlPressed) { int amount = 1; if (shiftPressed && stackInSlot != null) amount = stackInSlot.getMaxStackSize(); - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_MOVE, new int[]{slot.index, amount}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_MOVE, creativeSlotArgs(slot, amount), this.mc.thePlayer); } else { - this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, new int[]{slot.index, 1}, this.mc.thePlayer); + this.mc.playerController.handleInventoryMouseClick(this.inventorySlots.containerId, InventoryAction.CREATIVE_GRAB, creativeSlotArgs(slot, 1), this.mc.thePlayer); } } return; diff --git a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java index 4767708ca..90b1e8cdb 100644 --- a/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java +++ b/game/client/src/main/java/net/minecraft/client/gui/container/ScreenInventoryCreative.java @@ -116,11 +116,7 @@ public class ScreenInventoryCreative extends ScreenInventory implements ITextCha GameSettings.LAST_CREATIVE_INVENTORY_PAGE.set(clamped); GameSettings.saveOptions(); } - if (clamped == this.container.page) { - this.container.broadcastInventoryStatus(); - } else { - this.container.setInventoryStatus(clamped, this.container.searchText); - } + this.container.setInventoryStatus(clamped, this.container.searchText); } private void persistCreativeInventoryPage() { diff --git a/game/client/src/main/java/net/minecraft/client/option/GameSettings.java b/game/client/src/main/java/net/minecraft/client/option/GameSettings.java index 8d835be10..74705fb43 100644 --- a/game/client/src/main/java/net/minecraft/client/option/GameSettings.java +++ b/game/client/src/main/java/net/minecraft/client/option/GameSettings.java @@ -247,6 +247,7 @@ public final class GameSettings { .addOnChangeCallback((mc, option) -> mc.gameWindow.setVsync(option.value))); public static final @NotNull OptionEnum chatVisibility = register(new OptionEnum<>("chatVisibility", ChatVisibility.class, ChatVisibility.SHOW_ALL)); public static final @NotNull OptionRange CUSTOM_FPS_LIMIT = register(new OptionRange("customFpsLimit", 165, 301) + .withStep(5) .withDisplayStringProvider((mc, i18n, option) -> { int value = option.value; int maxValue = 300; diff --git a/game/client/src/main/java/net/minecraft/client/option/OptionRange.java b/game/client/src/main/java/net/minecraft/client/option/OptionRange.java index 36a7d9096..9cbb077c9 100644 --- a/game/client/src/main/java/net/minecraft/client/option/OptionRange.java +++ b/game/client/src/main/java/net/minecraft/client/option/OptionRange.java @@ -5,6 +5,8 @@ import org.jetbrains.annotations.NotNull; public class OptionRange extends OptionToggleable { public final int highest; public final int lowest; + public int step = 1; + public OptionRange(@NotNull String name, int defaultValue, int values) { super(name, defaultValue, getValueArray(values)); this.highest = this.values[this.values.length - 1]; @@ -41,6 +43,11 @@ public class OptionRange extends OptionToggleable { return array; } + public OptionRange withStep(int step) { + this.step = step; + return this; + } + @Override public boolean isSlider() { return true; diff --git a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerMP.java b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerMP.java index 4dc8f5ed9..8dcb91476 100644 --- a/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerMP.java +++ b/game/client/src/main/java/net/minecraft/client/player/controller/PlayerControllerMP.java @@ -80,21 +80,21 @@ public class PlayerControllerMP @Override public boolean useOrPlaceItemStackOnTile(final @NotNull Player player, final @NotNull World world, final @Nullable ItemStack itemStack, final @NotNull TilePosc tilePos, final @NotNull Side side, final double xPlaced, final double yPlaced) { this.syncCurrentPlayItem(); - this.packetHandler.addToSendQueue(new PacketUseOrPlaceItemStack(tilePos.x(), tilePos.y(), tilePos.z(), side.direction(), player.inventory.getCurrentItem(), xPlaced, yPlaced, PacketUseOrPlaceItemStack.TYPE_USE_OR_PLACE_ON_TILE)); + this.packetHandler.addToSendQueue(new PacketUseOrPlaceItemStack(tilePos.x(), tilePos.y(), tilePos.z(), side.direction(), ItemStack.copyItemStack(player.inventory.getCurrentItem()), xPlaced, yPlaced, PacketUseOrPlaceItemStack.TYPE_USE_OR_PLACE_ON_TILE)); return super.useOrPlaceItemStackOnTile(player, world, itemStack, tilePos, side, xPlaced, yPlaced); } @Override public boolean useItemStackOnNothing(final @NotNull Player player, final @NotNull World world, final @NotNull ItemStack itemStack) { this.syncCurrentPlayItem(); - this.packetHandler.addToSendQueue(new PacketUseOrPlaceItemStack(-1, -1, -1, Direction.NONE, player.inventory.getCurrentItem(), 0, 0, PacketUseOrPlaceItemStack.TYPE_USE_ON_NOTHING)); + this.packetHandler.addToSendQueue(new PacketUseOrPlaceItemStack(-1, -1, -1, Direction.NONE, ItemStack.copyItemStack(player.inventory.getCurrentItem()), 0, 0, PacketUseOrPlaceItemStack.TYPE_USE_ON_NOTHING)); return super.useItemStackOnNothing(player, world, itemStack); } @Override public boolean placeItemStackOnTile(final @NotNull Player player, final @NotNull World world, final @Nullable ItemStack itemStack, final @NotNull TilePosc tilePos, final @NotNull Side side, final double xPlaced, final double yPlaced) { this.syncCurrentPlayItem(); - this.packetHandler.addToSendQueue(new PacketUseOrPlaceItemStack(tilePos.x(), tilePos.y(), tilePos.z(), side.direction(), player.inventory.getCurrentItem(), xPlaced, yPlaced, PacketUseOrPlaceItemStack.TYPE_PLACE_ONLY)); + this.packetHandler.addToSendQueue(new PacketUseOrPlaceItemStack(tilePos.x(), tilePos.y(), tilePos.z(), side.direction(), ItemStack.copyItemStack(player.inventory.getCurrentItem()), xPlaced, yPlaced, PacketUseOrPlaceItemStack.TYPE_PLACE_ONLY)); return super.placeItemStackOnTile(player, world, itemStack, tilePos, side, xPlaced, yPlaced); } diff --git a/game/core/src/main/java/net/minecraft/core/Global.java b/game/core/src/main/java/net/minecraft/core/Global.java index e52cbd558..3a4249ab4 100644 --- a/game/core/src/main/java/net/minecraft/core/Global.java +++ b/game/core/src/main/java/net/minecraft/core/Global.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; public class Global { - public static final int TICKS_PER_SECOND = 21; + public static final int TICKS_PER_SECOND = 20; public static final int DAY_LENGTH_TICKS = 24000; public static final @NotNull String VERSION = Version.BUILD_CHANNEL.modifyVersionString(Version.VERSION); public static final @NotNull BuildChannel BUILD_CHANNEL = Version.BUILD_CHANNEL; diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java index 5ea60b1f3..bb7863a17 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicActivator.java @@ -41,7 +41,7 @@ public class BlockLogicActivator @Override public int tickDelay() { - return 4; + return 2; } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java index 5ffc6f297..90ee521e1 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluid.java @@ -23,7 +23,7 @@ import org.joml.primitives.AABBdc; import java.util.Random; -public abstract class BlockLogicFluid extends BlockLogic { +public abstract class BlockLogicFluid extends BlockLogic implements BlockLogic.MatcherDataEquivalency { public final @NotNull Fluid fluid; protected static final Direction[] CHECK_HARDEN_DIRECTIONS = new Direction[] {Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, Direction.UP}; @@ -240,10 +240,9 @@ public abstract class BlockLogicFluid extends BlockLogic { @Override protected boolean isEquivalentBlockForMatcher(@NotNull Block other) { if (other == this.block) return true; - return other.getLogic() instanceof BlockLogicFluid fluid && fluid.material == this.material; + return other.getLogic() instanceof BlockLogicFluid fluidBlock && this.fluid.equals(fluidBlock.fluid); } - public static boolean isStillEquivalentToFlowing(Block block1, Block block2) { if (block1 == null || block2 == null) return false; if (block1 == block2) return true; @@ -251,7 +250,7 @@ public abstract class BlockLogicFluid extends BlockLogic { if (block1.getLogic() instanceof BlockLogicFluid blockLogic1 && block2.getLogic() instanceof BlockLogicFluid blockLogic2) { - return blockLogic1.fluid == blockLogic2.fluid; + return blockLogic1.fluid.equals(blockLogic2.fluid); } return false; diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java index 92852658d..b8c1f305c 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFluidFlowing.java @@ -14,7 +14,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import java.util.Arrays; import java.util.Random; -public class BlockLogicFluidFlowing extends BlockLogicFluid implements BlockLogic.MatcherDataEquivalency { +public class BlockLogicFluidFlowing extends BlockLogicFluid { int maxCount; public final @NotNull Block blockStill; @@ -52,7 +52,7 @@ public class BlockLogicFluidFlowing extends BlockLogicFluid implements BlockLogi if (flowDecayAbove >= 8) { newFlowDecay = flowDecayAbove; } else if (flowDecayAbove >= 0) { - newFlowDecay = flowDecayAbove + 8; + newFlowDecay = 8; } // Become source block if (this.maxCount >= 2 && this.fluid.canBecomeSource(this, world, tilePos, rand)) { diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java index 13508dc26..f7c95559d 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicMatcher.java @@ -35,7 +35,7 @@ public class BlockLogicMatcher extends BlockLogicAxisAligned { @Override public int tickDelay() { - return 4; + return 2; } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBase.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBase.java index 8ec08268a..50eabce42 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBase.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicSaplingBase.java @@ -15,6 +15,7 @@ import org.jetbrains.annotations.Nullable; public abstract class BlockLogicSaplingBase extends BlockLogicFlower /*implements IBonemealable*/ { public boolean canGrowOnSand = false; + public static final int GROWTH_MASK = 8; public BlockLogicSaplingBase(@NotNull Block block) { super(block); @@ -48,8 +49,8 @@ public abstract class BlockLogicSaplingBase extends BlockLogicFlower /*implement } if (world.getBlockLightValue(tilePos.up(queryPos)) >= 9 && rand.nextInt(growthRate) == 0) { int l = world.getBlockData(tilePos); - if ((l & 8) == 0) { - world.setBlockData(tilePos, l | 8); + if ((l & GROWTH_MASK) == 0) { + world.setBlockData(tilePos, l | GROWTH_MASK); } else { growTree(world, tilePos, rand); } @@ -68,4 +69,9 @@ public abstract class BlockLogicSaplingBase extends BlockLogicFlower /*implement } public abstract void growTree(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Random random); + + @Override + public int getMatcherDataEquivalencyMask() { + return super.getMatcherDataEquivalencyMask() & ~GROWTH_MASK; + } } diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTimer.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTimer.java index ab3dbeafc..204ca8960 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTimer.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTimer.java @@ -30,7 +30,7 @@ public class BlockLogicTimer extends BlockLogic implements ISupportable, BlockLo -0.0625D, 0.0625D, 0.1875D, 0.3125D }; public static final int[] tickDelayMap = { - 4, 8, 12, 16 + 2, 4, 6, 8 }; public static final int MASK_AXIS = 0b0000_0001; diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java b/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java index 62745563d..278b1fb4a 100644 --- a/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java +++ b/game/core/src/main/java/net/minecraft/core/block/FluidAcid.java @@ -14,8 +14,10 @@ import org.jetbrains.annotations.NotNull; import java.util.Random; public class FluidAcid implements Fluid { - public FluidAcid() { - } + @Override + public boolean equals(Object obj) { + return obj instanceof FluidAcid; + } @Override public int tickDelay() { diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidLava.java b/game/core/src/main/java/net/minecraft/core/block/FluidLava.java index 4e08fd416..43430dbce 100644 --- a/game/core/src/main/java/net/minecraft/core/block/FluidLava.java +++ b/game/core/src/main/java/net/minecraft/core/block/FluidLava.java @@ -14,6 +14,12 @@ import java.util.Random; public class FluidLava implements Fluid { + + @Override + public boolean equals(Object obj) { + return obj instanceof FluidLava; + } + @Override public int tickDelay() { return 30; diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidWater.java b/game/core/src/main/java/net/minecraft/core/block/FluidWater.java index 3336d57b1..997d673f3 100644 --- a/game/core/src/main/java/net/minecraft/core/block/FluidWater.java +++ b/game/core/src/main/java/net/minecraft/core/block/FluidWater.java @@ -15,6 +15,12 @@ import java.util.Random; public class FluidWater implements Fluid { + + @Override + public boolean equals(Object obj) { + return obj instanceof FluidWater; + } + @Override public int tickDelay() { return 5; diff --git a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java index dbeb39bd4..d7dc626da 100644 --- a/game/core/src/main/java/net/minecraft/core/entity/player/Player.java +++ b/game/core/src/main/java/net/minecraft/core/entity/player/Player.java @@ -1267,9 +1267,10 @@ public abstract class Player if (this.yd < 0.0D) { damage++; } + boolean wasAlive = entity.isAlive(); entity.hurt(this, damage, DamageType.COMBAT); ItemStack itemstack = getCurrentEquippedItem(); - if (itemstack != null && (entity instanceof Mob)) { + if (itemstack != null && (entity instanceof Mob) && wasAlive) { itemstack.hitEntity((Mob) entity, this); if (itemstack.stackSize <= 0) { destroyCurrentEquippedItem(); @@ -1524,9 +1525,6 @@ public abstract class Player this.inventory.setCurrentItem(item); } - public void updateCreativeInventory(int page, String searchText) { - } - public @Nullable TilePos getPlayerSpawnPoint() { return this.playerSpawnPoint; } diff --git a/game/core/src/main/java/net/minecraft/core/net/handler/PacketHandler.java b/game/core/src/main/java/net/minecraft/core/net/handler/PacketHandler.java index 609a47978..efa30dad7 100644 --- a/game/core/src/main/java/net/minecraft/core/net/handler/PacketHandler.java +++ b/game/core/src/main/java/net/minecraft/core/net/handler/PacketHandler.java @@ -260,10 +260,6 @@ public abstract class PacketHandler { handleInvalidPacket(packetPlayerGamemode); } - public void handleUpdateCreativeInventory(@NotNull PacketUpdateCreativeInventory packetUpdateCreativeInventory) { - handleInvalidPacket(packetUpdateCreativeInventory); - } - public void handleWeatherStatus(@NotNull PacketWeatherStatus packetWeatherStatus) { handleInvalidPacket(packetWeatherStatus); } diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java b/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java index c871d0372..42581b9eb 100644 --- a/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java +++ b/game/core/src/main/java/net/minecraft/core/net/packet/Packet.java @@ -318,7 +318,6 @@ public abstract class Packet addMapping(104, true, false, PacketContainerSetContent.class); addMapping(105, true, false, PacketContainerSetData.class); addMapping(106, true, true, PacketContainerAck.class); - addMapping(107, false, true, PacketUpdateCreativeInventory.class); addMapping(108, true, true, PacketSetHotbarOffset.class); addMapping(120, true, false, PacketCommandManager.class); addMapping(121, false, true, PacketRequestCommandManager.class); diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerClick.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerClick.java index 3afb71bb0..6cab152be 100644 --- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerClick.java +++ b/game/core/src/main/java/net/minecraft/core/net/packet/PacketContainerClick.java @@ -45,7 +45,7 @@ public class PacketContainerClick extends Packet { int size = dis.readByte(); args = new int[size]; for(int i=0; i < size; i++) { - args[i] = dis.read(); + args[i] = dis.readInt(); } stateId = dis.readInt(); @@ -76,7 +76,7 @@ public class PacketContainerClick extends Packet { }else { dos.write(args.length); for(int i=0; i < args.length; i++) { - dos.write(args[i]); + dos.writeInt(args[i]); } } }else { @@ -122,6 +122,6 @@ public class PacketContainerClick extends Packet { @Override public int getEstimatedSize() { - return 11 + (args != null ? args.length : 0) + (changedSlots != null ? changedSlots.size() * 7 : 0); + return 11 + (args != null ? args.length * 4 : 0) + (changedSlots != null ? changedSlots.size() * 7 : 0); } } diff --git a/game/core/src/main/java/net/minecraft/core/net/packet/PacketUpdateCreativeInventory.java b/game/core/src/main/java/net/minecraft/core/net/packet/PacketUpdateCreativeInventory.java deleted file mode 100644 index 2b2745a7c..000000000 --- a/game/core/src/main/java/net/minecraft/core/net/packet/PacketUpdateCreativeInventory.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.minecraft.core.net.packet; - -import net.minecraft.core.net.handler.PacketHandler; - -import java.io.*; - -public class PacketUpdateCreativeInventory extends Packet -{ - - public PacketUpdateCreativeInventory() - { - } - - public PacketUpdateCreativeInventory(int windowId, int page, String searchText) - { - this.windowId = windowId; - this.page = page; - this.searchText = searchText; - } - - @Override - public void handlePacket(PacketHandler packetHandler) - { - packetHandler.handleUpdateCreativeInventory(this); - } - - @Override - public void read(DataInputStream dis) - throws IOException - { - windowId = dis.readByte(); - page = dis.readInt(); - searchText = dis.readUTF(); - } - - @Override - public void write(DataOutputStream dos) - throws IOException - { - dos.writeByte(windowId); - dos.writeInt(page); - dos.writeUTF(searchText); - } - - @Override - public int getEstimatedSize() - { - return 4 + 4 + searchText.length() * 2; - } - - public int windowId; - public int page; - public String searchText; -} diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java index 7f02e44c3..57a3f5d05 100644 --- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java +++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuAbstract.java @@ -16,6 +16,7 @@ import net.minecraft.core.item.ItemStack; import net.minecraft.core.player.inventory.container.Container; import net.minecraft.core.player.inventory.container.ContainerInventory; import net.minecraft.core.player.inventory.slot.Slot; +import net.minecraft.core.player.inventory.slot.SlotCreative; import net.minecraft.core.player.inventory.slot.SlotResult; import net.minecraft.core.util.helper.MathHelper; import org.jetbrains.annotations.NotNull; @@ -322,16 +323,23 @@ public abstract class MenuAbstract } } }else { + ItemStack sourceStack = stackInSlot; + if(slot instanceof SlotCreative) { + sourceStack = args.length >= 4 ? MenuInventoryCreative.getValidCreativeItem(args[2], args[3]) : null; + if(sourceStack == null && args.length >= 4 && args[2] != 0) { + LOGGER.warn("Player {} requested item {}:{} which the creative menu does not offer!", player.username, args[2], args[3]); + } + } int amount = args.length > 1 ? args[1] : 0; - if(stackInSlot != null) { - amount = MathHelper.clamp(amount, 0, stackInSlot.getMaxStackSize()); + if(sourceStack != null) { + amount = MathHelper.clamp(amount, 0, sourceStack.getMaxStackSize()); }else { amount = 0; } if(action == InventoryAction.CREATIVE_GRAB) { ItemStack stack; if(amount > 0) { - stack = slot.getItemStack().copy(); + stack = sourceStack.copy(); stack.stackSize = amount; }else { stack = null; @@ -340,7 +348,7 @@ public abstract class MenuAbstract } if(action == InventoryAction.CREATIVE_MOVE) { if(amount > 0) { - ItemStack stack = slot.getItemStack().copy(); + ItemStack stack = sourceStack.copy(); stack.stackSize = amount; player.inventory.insertItem(stack, false); } @@ -490,7 +498,13 @@ public abstract class MenuAbstract return; } - ItemStack slotStack = slot.getItemStack(); + ItemStack slotStack; + if(slot instanceof SlotCreative) { + slotStack = args.length >= 4 ? MenuInventoryCreative.getValidCreativeItem(args[2], args[3]) : null; + } else { + assert slot != null; + slotStack = slot.getItemStack(); + } ItemStack hotbarStack = hotbarSlot.getItemStack(); if(slotStack != null) { diff --git a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java index d91a68214..a202503be 100644 --- a/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java +++ b/game/core/src/main/java/net/minecraft/core/player/inventory/menu/MenuInventoryCreative.java @@ -151,13 +151,18 @@ public class MenuInventoryCreative extends MenuInventory ((SlotCreative)this.slots.get(creativeSlotsStart + i)).item = searchedItems.get(idx); } } - - inventory.player.updateCreativeInventory(page, searchText); } - public void broadcastInventoryStatus() + public static ItemStack getValidCreativeItem(int itemId, int metadata) { - inventory.player.updateCreativeInventory(page, searchText); + for (ItemStack stack : creativeContents) + { + if (stack != null && stack.itemID == itemId && stack.getMetadata() == metadata) + { + return stack.copy(); + } + } + return null; } public String getSearchText(){ diff --git a/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java b/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java index 06ea8e0b1..2a51cfea4 100644 --- a/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java +++ b/game/core/src/main/java/net/minecraft/core/world/PortalHandler.java @@ -5,6 +5,10 @@ import net.minecraft.core.block.BlockLogicPortal; import net.minecraft.core.entity.Entity; import net.minecraft.core.util.helper.DyeColor; import net.minecraft.core.util.helper.MathHelper; +import net.minecraft.core.world.chunk.Chunk; +import net.minecraft.core.world.chunk.provider.ChunkProvider; +import net.minecraft.core.world.pos.ChunkPos; +import net.minecraft.core.world.pos.ChunkTilePos; import net.minecraft.core.world.pos.TilePos; import net.minecraft.core.world.type.WorldType; import org.jetbrains.annotations.Nullable; @@ -61,38 +65,80 @@ public class PortalHandler targetPortal = newDim.portalBlock; } - // Attempt to find closest portal along the xz plane - for(int dx = entityBlockX - searchRadius; dx <= entityBlockX + searchRadius; dx++) + if(targetPortal == null) { - double xEntityDistance = ((double)dx + 0.5D) - entity.x; - for(int dz = entityBlockZ - searchRadius; dz <= entityBlockZ + searchRadius; dz++) + return false; + } + + // Attempt to find closest portal along the xz plane. + + // Portals can only exist in chunks that were generated before, so the search now only visits + // chunks that are already loaded or saved on disk. + + int targetPortalId = targetPortal.id(); + int maxPortalY = newWorldType.getMaxPortalY(); + int minPortalY = newWorldType.getMinPortalY(); + ChunkProvider chunkProvider = world.getChunkProvider(); + ChunkPos chunkQueryPos = new ChunkPos(); + ChunkTilePos chunkTileQueryPos = new ChunkTilePos(); + TilePos colorQueryPos = new TilePos(); + int minBlockX = entityBlockX - searchRadius; + int maxBlockX = entityBlockX + searchRadius; + int minBlockZ = entityBlockZ - searchRadius; + int maxBlockZ = entityBlockZ + searchRadius; + for(int chunkX = minBlockX >> 4; chunkX <= maxBlockX >> 4; chunkX++) + { + for(int chunkZ = minBlockZ >> 4; chunkZ <= maxBlockZ >> 4; chunkZ++) { - double zEntityDistance = ((double)dz + 0.5D) - entity.z; - for(int dy = newWorldType.getMaxPortalY() - 1; dy >= newWorldType.getMinPortalY(); dy--) + chunkQueryPos.set(chunkX, chunkZ); + if(!chunkProvider.chunkExists(chunkQueryPos)) { - if(world.getBlock(dx, dy, dz) != targetPortal) + continue; + } + Chunk chunk = chunkProvider.provideChunk(chunkQueryPos, true); + if(!chunk.isAtLocation(chunkQueryPos)) + { + // The provider returned a placeholder chunk instead of the real one + continue; + } + int startX = Math.max(minBlockX, chunkX * Chunk.CHUNK_SIZE_X); + int endX = Math.min(maxBlockX, chunkX * Chunk.CHUNK_SIZE_X + Chunk.CHUNK_SIZE_X - 1); + int startZ = Math.max(minBlockZ, chunkZ * Chunk.CHUNK_SIZE_Z); + int endZ = Math.min(maxBlockZ, chunkZ * Chunk.CHUNK_SIZE_Z + Chunk.CHUNK_SIZE_Z - 1); + for(int dx = startX; dx <= endX; dx++) + { + double xEntityDistance = ((double)dx + 0.5D) - entity.x; + for(int dz = startZ; dz <= endZ; dz++) { - continue; - } + double zEntityDistance = ((double)dz + 0.5D) - entity.z; + for(int dy = maxPortalY - 1; dy >= minPortalY; dy--) + { + if(chunk.getBlockId(chunkTileQueryPos.set(dx, dy, dz)) != targetPortalId) + { + continue; + } - if (portalColor != null && targetPortal != null && targetPortal.getLogic().getColor(world, dx, dy, dz) != portalColor) { - continue; - } + if (portalColor != null && targetPortal.getLogic().getColor(world, colorQueryPos.set(dx, dy, dz)) != portalColor) { + continue; + } - // Find the bottom portal block of the portal - for(; world.getBlock(dx, dy - 1, dz) == targetPortal; dy--); + // Find the bottom portal block of the portal + for(; dy > 0 && chunk.getBlockId(chunkTileQueryPos.set(dx, dy - 1, dz)) == targetPortalId; dy--); + +// double yEntityDistance = ((double)dy + 0.5D) - entityPosYScaled; + double entityDistanceSquared = xEntityDistance * xEntityDistance /*+ yEntityDistance * yEntityDistance*/ + zEntityDistance * zEntityDistance; + if(lowestEntityDistanceSquaredXZ < 0.0D || entityDistanceSquared < lowestEntityDistanceSquaredXZ) + { + lowestEntityDistanceSquaredXZ = entityDistanceSquared; + closestPortalX = dx; + closestPortalY = dy; + closestPortalZ = dz; + } + } -// double yEntityDistance = ((double)dy + 0.5D) - entityPosYScaled; - double entityDistanceSquared = xEntityDistance * xEntityDistance /*+ yEntityDistance * yEntityDistance*/ + zEntityDistance * zEntityDistance; - if(lowestEntityDistanceSquaredXZ < 0.0D || entityDistanceSquared < lowestEntityDistanceSquaredXZ) - { - lowestEntityDistanceSquaredXZ = entityDistanceSquared; - closestPortalX = dx; - closestPortalY = dy; - closestPortalZ = dz; } - } + } } } diff --git a/game/core/src/main/java/net/minecraft/core/world/World.java b/game/core/src/main/java/net/minecraft/core/world/World.java index 84197e86c..8c866a257 100644 --- a/game/core/src/main/java/net/minecraft/core/world/World.java +++ b/game/core/src/main/java/net/minecraft/core/world/World.java @@ -2455,7 +2455,11 @@ public abstract class World implements MutableWorldSource { } public void unloadEntities(final List list) { - this.entitiesToRemove.addAll(list); + for (final Entity entity : list) { + if (!(entity instanceof Player)) { + this.entitiesToRemove.add(entity); + } + } } public void dropOldChunks() { diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java b/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java index 4d678cdf0..84f3b9af6 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/Chunk.java @@ -167,6 +167,9 @@ public class Chunk { } public void checkForLightGaps() { + if (this.world.getWorldType().hasCeiling()) { + return; + } for (int x = 0; x < CHUNK_SIZE_X; x++) { for (int z = 0; z < CHUNK_SIZE_Z; z++) { lightGaps(x, z); diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoader.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoader.java index 96b6b1048..187b281b6 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoader.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoader.java @@ -26,6 +26,15 @@ public interface ChunkLoader void saveChunk(World world, Chunk chunk) throws IOException; + /** + * Checks whether a chunk has previously been saved to disk, without loading it. + * @param world The world the chunk belongs to. + * @param x The X coordinate of the chunk. + * @param z The Z coordinate of the chunk. + * @return true if the chunk can be loaded from disk. + */ + boolean chunkExists(World world, int x, int z); + /** * @return true if busy saving diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java index c731aeac4..0b5e3be86 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderLegacy.java @@ -165,6 +165,15 @@ public class ChunkLoaderLegacy } } + @Override + public boolean chunkExists(World world, int x, int z) + { + String fileName = "c." + Integer.toString(x, 36) + "." + Integer.toString(z, 36) + ".dat"; + String xDirName = Integer.toString(x & 0x3f, 36); + String zDirName = Integer.toString(z & 0x3f, 36); + return new File(new File(new File(worldDir, xDirName), zDirName), fileName).exists(); + } + @Override public boolean isSaving() { return false; diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java index 4d9a5f59f..3e9bd7609 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegion.java @@ -87,6 +87,12 @@ public class ChunkLoaderRegion } } + @Override + public boolean chunkExists(World world, int x, int z) + { + return RegionFileCache.chunkExists(worldDir, x, z); + } + @Override public boolean isSaving() { return false; diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java index 995322c38..df0140e39 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkLoaderRegionAsync.java @@ -64,6 +64,32 @@ public class ChunkLoaderRegionAsync } } + @Override + public boolean chunkExists(World world, int x, int z) + { + //chunks waiting in the save queue exist + lockChunksToSave.lock(); + try + { + java.util.Iterator chunkIterator = chunksToSave.iterator(); + java.util.Iterator worldIterator = worldsToSave.iterator(); + while (chunkIterator.hasNext() && worldIterator.hasNext()) + { + Chunk chunk = chunkIterator.next(); + World chunkWorld = worldIterator.next(); + if (chunkWorld == world && chunk.pos.x == x && chunk.pos.z == z) + { + return true; + } + } + } + finally + { + lockChunksToSave.unlock(); + } + return chunkLoaderRegion.chunkExists(world, x, z); + } + @Override public boolean isSaving() { return !chunksToSave.isEmpty(); diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProvider.java b/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProvider.java index 7e370efbd..d4dd197fc 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProvider.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProvider.java @@ -15,6 +15,10 @@ public interface ChunkProvider { } boolean isChunkLoaded(@NotNull ChunkPosc chunkPos); + default boolean chunkExists(@NotNull ChunkPosc chunkPos) { + return isChunkLoaded(chunkPos); + } + @Deprecated default @NotNull Chunk provideChunk(int chunkX, int chunkZ) { return provideChunk(new ChunkPos(chunkX, chunkZ), true); diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProviderThreaded.java b/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProviderThreaded.java index 8ffa47a9e..6e2c0b182 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProviderThreaded.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/provider/ChunkProviderThreaded.java @@ -73,6 +73,19 @@ public class ChunkProviderThreaded implements ChunkProvider { return isLoaded; } + @Override + public boolean chunkExists(@NotNull ChunkPosc chunkPos) { + if (isChunkLoaded(chunkPos)) { + return true; + } + synchronized (this.preparedUndecoratedChunks) { + if (this.preparedUndecoratedChunks.containsKey(chunkPos)) { + return true; + } + } + return this.chunkLoader.chunkExists(this.world, chunkPos.x(), chunkPos.z()); + } + @Override public @NotNull Chunk provideChunk(@NotNull ChunkPosc chunkPos, boolean priority) { if (chunkPos.equals(this.lastQueriedChunkPos)) return this.lastQueriedChunk; diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java index b1d2967af..8d7f9e51c 100644 --- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java +++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/ChunkDecoratorNether.java @@ -20,6 +20,7 @@ import net.minecraft.core.world.generate.feature.WorldFeatureNetherScatterEmberA import net.minecraft.core.world.noise.FractalNoise2D; import net.minecraft.core.world.noise.ImprovedPerlinNoise; import net.minecraft.core.world.noise.WorleyNoise; +import net.minecraft.core.world.pos.ChunkTilePos; import net.minecraft.core.world.pos.TilePos; import org.jetbrains.annotations.NotNull; @@ -339,28 +340,42 @@ public class ChunkDecoratorNether @Override public void postDecorate(@NotNull World world, @NotNull Chunk chunk) { - TilePos queryPose = new TilePos(); + TilePos placePos = new TilePos(); + ChunkTilePos queryPos = new ChunkTilePos(); int worldX = chunk.pos.x() * 16; int worldZ = chunk.pos.z() * 16; int startY = world.getWorldType().getMaxY(world); + int stopY = world.getWorldType().getOceanY(); - for (int dx = worldX; dx < worldX + 16; ++dx) { - for (int dz = worldZ; dz < worldZ + 16; ++dz) { - for (int dy = startY; dy > world.getWorldType().getOceanY(); --dy) { - queryPose.set(dx, dy, dz); + for (int x = 0; x < 16; ++x) { + for (int z = 0; z < 16; ++z) { + int blockId = chunk.getBlockId(queryPos.set(x, startY, z)); + Biome cachedBiome = null; + boolean cachedBiomeHasAsh = false; + int cachedBiomeCellY = Integer.MIN_VALUE; - if (world.isAirBlock(queryPose)) { - Block blockBelow = world.getBlock(dx, dy - 1, dz); + for (int y = startY; y > stopY; --y) { + // Each block is read once and reused as the blockBelow of the row above it + int blockBelowId = chunk.getBlockId(queryPos.set(x, y - 1, z)); + + if (blockId == 0 && blockBelowId != 0) { + Block blockBelow = Blocks.getBlock(blockBelowId); if (blockBelow != Blocks.OBSIDIAN && blockBelow != Blocks.SOULSAND && blockBelow.getMaterial().blocksMotion() && !isRubyglassAshSupportForbidden(blockBelow)) { - Biome localBiome = world.getBlockBiome(queryPose); - if (localBiome.hasTag(BiomeTags.HAS_SURFACE_ASH)) { - world.setBlockType(queryPose, Blocks.LAYER_ASH); + if ((y >> 3) != cachedBiomeCellY) { + cachedBiomeCellY = y >> 3; + cachedBiome = chunk.getBlockBiome(queryPos.set(x, y, z)); + cachedBiomeHasAsh = cachedBiome != null && cachedBiome.hasTag(BiomeTags.HAS_SURFACE_ASH); + } + if (cachedBiomeHasAsh) { + world.setBlockType(placePos.set(worldX + x, y, worldZ + z), Blocks.LAYER_ASH); } } } + + blockId = blockBelowId; } } } diff --git a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java index b75207a26..95f8afc70 100644 --- a/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java +++ b/game/core/src/main/java/net/minecraft/core/world/generate/chunk/perlin/nether/SurfaceGeneratorNether.java @@ -8,6 +8,7 @@ import net.minecraft.core.world.biome.Biomes; import net.minecraft.core.world.chunk.Chunk; import net.minecraft.core.world.generate.chunk.ChunkGeneratorResult; import net.minecraft.core.world.generate.chunk.perlin.SurfaceGenerator; +import net.minecraft.core.world.pos.ChunkTilePos; import net.minecraft.core.world.noise.FractalNoise3D; import net.minecraft.core.world.noise.ImprovedPerlinNoise; import org.jetbrains.annotations.NotNull; @@ -78,6 +79,8 @@ public class SurfaceGeneratorNether implements SurfaceGenerator { stoneLayerNoiseGloomstone = this.beachNoise.getRegion(null, chunkX * Chunk.CHUNK_SIZE_X, chunkZ * Chunk.CHUNK_SIZE_Z, 0.0D, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SIZE_Z, 1, beachScale * 4D, beachScale * 4D, beachScale * 4D); }*/ + ChunkTilePos biomeQueryPos = new ChunkTilePos(); + for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { int noiseIndex = z + x * 16; @@ -98,10 +101,17 @@ public class SurfaceGeneratorNether implements SurfaceGenerator { boolean cachedBiomeGeneratesSulfur = false; int cachedBiomeStoneBlockId = worldFillBlock; + Biome biome = null; + int lastBiomeCellY = Integer.MIN_VALUE; + for (int y = maxY; y >= minY; y--) { - Biome biome = chunk.getBlockBiome(x, y, z); - if (biome == null) { - biome = this.world.getBiomeProvider().getBiome(worldX, y >> 3, worldZ); + int biomeCellY = y >> 3; + if (biomeCellY != lastBiomeCellY) { + lastBiomeCellY = biomeCellY; + biome = chunk.getBlockBiome(biomeQueryPos.set(x, y, z)); + if (biome == null) { + biome = this.world.getBiomeProvider().getBiome(worldX, biomeCellY, worldZ); + } } if (biome != lastBiome) { diff --git a/game/core/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java b/game/core/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java index 8c4d9c351..4001ae3df 100644 --- a/game/core/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java +++ b/game/core/src/main/java/net/minecraft/core/world/save/mcregion/RegionFileCache.java @@ -67,6 +67,20 @@ public class RegionFileCache return regionfile.getSizeDeltaBytes(); } + public static synchronized boolean chunkExists(File worldDir, int x, int z) + { + File regionDir = new File(worldDir, "region"); + File regionFileName = new File(regionDir, "r." + (x >> 5) + "." + (z >> 5) + ".mcr"); + Reference reference = cache.get(regionFileName); + RegionFile cachedRegion = reference != null ? reference.get() : null; + if(cachedRegion == null && !regionFileName.exists()) + { + // Avoids creating an empty region file just to probe for a chunk + return false; + } + return loadRegionFileFromCoords(worldDir, x, z).chunkExists(x & 0x1f, z & 0x1f); + } + public static DataInputStream getChunkInputStream(File worldDir, int x, int z) { RegionFile regionFile = loadRegionFileFromCoords(worldDir, x, z); diff --git a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java index 120899d98..3d3aab87e 100644 --- a/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java +++ b/game/server/src/main/java/net/minecraft/server/entity/player/PlayerServer.java @@ -306,29 +306,55 @@ public class PlayerServer extends Player implements ContainerListener { } public void tickSendChunks() { - if (!loadedChunks.isEmpty()) + + if (loadedChunks.isEmpty()) return; + + WorldServer worldserver = mcServer.getDimensionWorld(dimension); + + final long timeBudgetNanos = 8_000_000L; + long startTime = System.nanoTime(); + int chunksSent = 0; + while (!loadedChunks.isEmpty() && playerNetServerHandler.getNumChunkDataPackets() < 8) { ChunkCoordinate chunkCoord = (ChunkCoordinate) loadedChunks.get(0); - if (chunkCoord != null) + if (chunkCoord == null) + { + break; + } + if (chunksSent > 0 && (System.nanoTime() - startTime > timeBudgetNanos || !isChunkNeighborhoodLoaded(worldserver, chunkCoord))) { - boolean canSendMoreDataPackets = playerNetServerHandler.getNumChunkDataPackets() < 8; - if (canSendMoreDataPackets) + break; + } + loadedChunks.remove(0); + ChunkPos sentChunkPos = new ChunkPos(chunkCoord.x, chunkCoord.z); + worldserver.getChunkProvider().prepareChunk(sentChunkPos, true); + worldserver.getChunkProvider().ensureDecorated(sentChunkPos); + worldserver.getChunk(sentChunkPos, true).sentToClients = true; + playerNetServerHandler.sendPacket(new PacketBlockRegionUpdate(chunkCoord.x * Chunk.CHUNK_SIZE_X, 0, chunkCoord.z * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, Chunk.CHUNK_SIZE_Z, worldserver)); + List list = worldserver.getBlockEntitiesWithinBounds(chunkCoord.x * Chunk.CHUNK_SIZE_X, 0, chunkCoord.z * Chunk.CHUNK_SIZE_Z, chunkCoord.x * Chunk.CHUNK_SIZE_X + Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, chunkCoord.z * Chunk.CHUNK_SIZE_Z + Chunk.CHUNK_SIZE_Z); + for (int j = 0; j < list.size(); j++) + { + getTileEntityInfo(list.get(j)); + } + chunksSent++; + } + } + + private boolean isChunkNeighborhoodLoaded(WorldServer worldserver, ChunkCoordinate chunkCoord) + { + ChunkPos queryPos = new ChunkPos(); + for (int dx = -1; dx <= 1; dx++) + { + for (int dz = -1; dz <= 1; dz++) + { + queryPos.set(chunkCoord.x + dx, chunkCoord.z + dz); + if (!worldserver.getChunkProvider().isChunkLoaded(queryPos)) { - WorldServer worldserver = mcServer.getDimensionWorld(dimension); - loadedChunks.remove(chunkCoord); - ChunkPos sentChunkPos = new ChunkPos(chunkCoord.x, chunkCoord.z); - worldserver.getChunkProvider().prepareChunk(sentChunkPos, true); - worldserver.getChunkProvider().ensureDecorated(sentChunkPos); - worldserver.getChunk(sentChunkPos, true).sentToClients = true; - playerNetServerHandler.sendPacket(new PacketBlockRegionUpdate(chunkCoord.x * Chunk.CHUNK_SIZE_X, 0, chunkCoord.z * Chunk.CHUNK_SIZE_Z, Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, Chunk.CHUNK_SIZE_Z, worldserver)); - List list = worldserver.getBlockEntitiesWithinBounds(chunkCoord.x * Chunk.CHUNK_SIZE_X, 0, chunkCoord.z * Chunk.CHUNK_SIZE_Z, chunkCoord.x * Chunk.CHUNK_SIZE_X + Chunk.CHUNK_SIZE_X, Chunk.CHUNK_SECTIONS * ChunkSection.SECTION_SIZE_Y, chunkCoord.z * Chunk.CHUNK_SIZE_Z + Chunk.CHUNK_SIZE_Z); - for (int j = 0; j < list.size(); j++) - { - getTileEntityInfo(list.get(j)); - } + return false; } } } + return true; } private void getTileEntityInfo(TileEntity tileentity) diff --git a/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java b/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java index 98061e04c..f9368fbc7 100644 --- a/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java +++ b/game/server/src/main/java/net/minecraft/server/net/handler/PacketHandlerServer.java @@ -27,7 +27,6 @@ import net.minecraft.core.net.handler.PacketHandler; import net.minecraft.core.net.packet.*; import net.minecraft.core.player.inventory.menu.MenuAbstract; import net.minecraft.core.player.inventory.menu.MenuFlag; -import net.minecraft.core.player.inventory.menu.MenuInventoryCreative; import net.minecraft.core.player.inventory.slot.Slot; import net.minecraft.core.util.helper.AES; import net.minecraft.core.util.helper.NetCharacters; @@ -743,13 +742,6 @@ public class PacketHandlerServer extends PacketHandler worldserver.markBlockNeedsUpdate(pos); } - @Override - public void handleUpdateCreativeInventory(@NotNull PacketUpdateCreativeInventory packet) { - if (this.playerEntity.containerMenu.containerId == packet.windowId && this.playerEntity.containerMenu instanceof MenuInventoryCreative) { - ((MenuInventoryCreative) this.playerEntity.containerMenu).setInventoryStatus(packet.page, packet.searchText); - } - } - @Override public void handleSetHotbarOffset(@NotNull PacketSetHotbarOffset packet) { diff --git a/game/server/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java b/game/server/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java index 4e505a68a..3f8a4a0e1 100644 --- a/game/server/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java +++ b/game/server/src/main/java/net/minecraft/server/world/chunk/provider/ChunkProviderServer.java @@ -48,6 +48,14 @@ public class ChunkProviderServer return this.chunkMap.containsKey(chunkPos); } + @Override + public boolean chunkExists(@NotNull ChunkPosc chunkPos) { + if (this.chunkMap.containsKey(chunkPos)) { + return true; + } + return this.chunkLoader != null && this.chunkLoader.chunkExists(this.world, chunkPos.x(), chunkPos.z()); + } + public void dropChunk(@NotNull ChunkPos chunkPos) { if (!this.chunkMap.containsKey(chunkPos)) {return;} TilePos spawnCoords = this.world.getSpawnPoint(); diff --git a/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java b/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java index cf27cb6f6..ec3d8fba8 100644 --- a/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java +++ b/util/datagen/src/main/java/net/minecraft/datagen/WorkbenchGenerator.java @@ -1478,6 +1478,7 @@ class WorkbenchGenerator { Registries.RECIPES.WORKBENCH.register("scrap_chainmail_leggings", new RecipeEntryScrap(Items.ARMOR_LEGGINGS_CHAINMAIL, Items.CHAINLINK, 4)); Registries.RECIPES.WORKBENCH.register("scrap_chainmail_chestplate", new RecipeEntryScrap(Items.ARMOR_CHESTPLATE_CHAINMAIL, Items.CHAINLINK, 4)); Registries.RECIPES.WORKBENCH.register("scrap_chainmail_helmet", new RecipeEntryScrap(Items.ARMOR_HELMET_CHAINMAIL, Items.CHAINLINK, 4)); + Registries.RECIPES.WORKBENCH.register("scrap_chainmail_wolf", new RecipeEntryScrap(Items.ARMOR_WOLF_CHAINMAIL, Items.CHAINLINK, 4)); } private static void generateRepairableRecipes() {