diff --git a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java index 9bad9c1ac..2b86ed7c2 100644 --- a/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java +++ b/game/client/src/main/java/net/minecraft/client/entity/player/PlayerLocal.java @@ -5,7 +5,6 @@ import com.mojang.logging.LogUtils; import com.mojang.nbt.tags.CompoundTag; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.hud.HudIngame; import net.minecraft.client.gui.hud.component.HudComponents; import net.minecraft.client.option.GameSettings; import net.minecraft.client.option.enums.ParticlesQuality; @@ -157,7 +156,7 @@ public class PlayerLocal extends Player { if (this.timeInPortal >= 1.0F || getGamemode().hasInstantPortalTravel()) { this.timeInPortal = 1.0F; if (!this.world.isClientSide) { - this.timeUntilPortal = 10; + this.timeUntilPortal = PORTAL_DELAY_TICKS; this.mc.sndManager.playSound("portal.travel", SoundCategory.WORLD_SOUNDS, 1.0F, this.random.nextFloat() * 0.4F + 0.8F); Dimension targetDim = ((BlockLogicPortal) Blocks.blocksList[this.portalID].getLogic()).targetDimension; if (this.dimension == targetDim.id) { diff --git a/game/client/src/main/java/net/minecraft/client/gui/CycleButtonElement.java b/game/client/src/main/java/net/minecraft/client/gui/CycleButtonElement.java new file mode 100644 index 000000000..d19d11eab --- /dev/null +++ b/game/client/src/main/java/net/minecraft/client/gui/CycleButtonElement.java @@ -0,0 +1,55 @@ +package net.minecraft.client.gui; + +import org.jetbrains.annotations.NotNull; + +import java.util.function.Function; + +public class CycleButtonElement extends ButtonElement { + private final T @NotNull [] values; + private final @NotNull Function labelGetter; + + private int index; + + public CycleButtonElement(int id, int xPosition, int yPosition, T @NotNull [] values, @NotNull T value, @NotNull Function labelGetter) { + this(id, xPosition, yPosition, 200, 20, values, value, labelGetter); + } + + public CycleButtonElement(int id, int xPosition, int yPosition, int width, int height, T @NotNull [] values, @NotNull T value, @NotNull Function labelGetter) { + super(id, xPosition, yPosition, width, height, ""); + + if (values.length == 0) { + throw new IllegalArgumentException("values must not be empty"); + } + this.values = values; + this.labelGetter = labelGetter; + this.setValue(value); + } + + public @NotNull T getValue() { + return this.values[this.index]; + } + + public void setValue(@NotNull T value) { + this.index = this.indexOf(value); + this.updateText(); + } + + public @NotNull T cycle() { + this.index = (this.index + 1) % this.values.length; + this.updateText(); + return this.getValue(); + } + + private int indexOf(@NotNull T value) { + for (int i = 0; i < this.values.length; i++) { + if (this.values[i].equals(value)) { + return i; + } + } + return 0; + } + + private void updateText() { + this.displayString = this.labelGetter.apply(this.getValue()); + } +} diff --git a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java index 913cdd37c..92be8e933 100644 --- a/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java +++ b/game/client/src/main/java/net/minecraft/client/gui/hud/component/HudComponentLog.java @@ -13,10 +13,7 @@ import net.minecraft.client.render.renderer.State; import net.minecraft.core.net.command.TextFormatting; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class HudComponentLog extends HudComponentMovable { private static final class LogEntry { @@ -71,7 +68,7 @@ public class HudComponentLog extends HudComponentMovable { return GameSettings.DEVELOPER_MODE.value; } - private void drawAlignedString(@NotNull FontRenderer sr, String text, int boxX, int boxY, int boxWidth, int argb) { + private void drawAlignedString(@NotNull FontRenderer sr, @NotNull String text, int boxX, int boxY, int boxWidth, int argb) { int textWidth = sr.stringWidth(text); float xMult = GameSettings.HORIZONTAL_LOG_TEXT_ALIGNMENT.value.multiplier; int renderX = boxX + PADDING + (int) ((boxWidth - (PADDING * 2) - textWidth) * xMult); @@ -124,11 +121,18 @@ public class HudComponentLog extends HudComponentMovable { } } - final @NotNull String @NotNull [] messages = new String[this.logEntries.size()]; - final float @NotNull [] opacities = new float[this.logEntries.size()]; - for (int i = 0; i < this.logEntries.size(); i++) { - messages[i] = this.logEntries.get(i).message; - opacities[i] = this.logEntries.get(i).getOpacity(); + final @NotNull String @NotNull [] messages; + final float @NotNull [] opacities; + + synchronized (this.logEntries) { + int size = this.logEntries.size(); + messages = new String[size]; + opacities = new float[size]; + for (int i = 0; i < size; i++) { + var entry = this.logEntries.get(i); + messages[i] = entry.message; + opacities[i] = entry.getOpacity(); + } } render(mc.font, x, y, messages, opacities); diff --git a/game/client/src/main/java/net/minecraft/client/gui/worldsettings/ScreenWorldSettings.java b/game/client/src/main/java/net/minecraft/client/gui/worldsettings/ScreenWorldSettings.java index d138d87a7..70d624cc5 100644 --- a/game/client/src/main/java/net/minecraft/client/gui/worldsettings/ScreenWorldSettings.java +++ b/game/client/src/main/java/net/minecraft/client/gui/worldsettings/ScreenWorldSettings.java @@ -7,10 +7,12 @@ import net.minecraft.client.gui.paged.PageComponent; import net.minecraft.client.gui.paged.PageRegistry; import net.minecraft.client.gui.paged.ScreenPaged; import net.minecraft.client.gui.worldsettings.gamerule.BooleanGameRuleComponent; +import net.minecraft.client.gui.worldsettings.gamerule.EnumGameRuleComponent; import net.minecraft.client.gui.worldsettings.settingnode.CategoryComponent; import net.minecraft.client.gui.worldsettings.settingnode.NestedNodeComponent; import net.minecraft.core.data.gamerule.GameRule; import net.minecraft.core.data.gamerule.GameRuleBoolean; +import net.minecraft.core.data.gamerule.GameRuleEnum; import net.minecraft.core.data.registry.Registries; import net.minecraft.core.entity.EntityDispatcher; import net.minecraft.core.entity.Mob; @@ -53,6 +55,8 @@ public class ScreenWorldSettings extends ScreenPaged implements WorldConfigurati for (final @NotNull GameRule gameRule : Registries.GAME_RULES) { if (gameRule instanceof GameRuleBoolean) { PAGE_GAME_RULES.withComponent(new BooleanGameRuleComponent((GameRuleBoolean) gameRule)); + } else if (gameRule instanceof GameRuleEnum) { + PAGE_GAME_RULES.withComponent(new EnumGameRuleComponent<>((GameRuleEnum) gameRule)); } } } @@ -92,6 +96,8 @@ public class ScreenWorldSettings extends ScreenPaged implements WorldConfigurati for (final @NotNull PageComponent component : gameRulesPageComponents) { if (component instanceof BooleanGameRuleComponent ruleComponent) { ruleComponent.setGameRuleCollection(worldConfiguration.getGameRules()); + } else if (component instanceof EnumGameRuleComponent ruleComponent) { + ruleComponent.setGameRuleCollection(worldConfiguration.getGameRules()); } } diff --git a/game/client/src/main/java/net/minecraft/client/gui/worldsettings/gamerule/EnumGameRuleComponent.java b/game/client/src/main/java/net/minecraft/client/gui/worldsettings/gamerule/EnumGameRuleComponent.java new file mode 100644 index 000000000..3bd20f75c --- /dev/null +++ b/game/client/src/main/java/net/minecraft/client/gui/worldsettings/gamerule/EnumGameRuleComponent.java @@ -0,0 +1,81 @@ +package net.minecraft.client.gui.worldsettings.gamerule; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.CycleButtonElement; +import net.minecraft.client.gui.worldsettings.ButtonComponent; +import net.minecraft.client.render.window.CursorShape; +import net.minecraft.core.data.gamerule.GameRuleCollection; +import net.minecraft.core.data.gamerule.GameRuleEnum; +import net.minecraft.core.lang.I18n; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; + +public class EnumGameRuleComponent> + extends ButtonComponent +{ + private @Nullable GameRuleCollection gameRuleCollection = null; + private final @NotNull GameRuleEnum gameRule; + private final @NotNull CycleButtonElement button; + + public EnumGameRuleComponent(final @NotNull GameRuleEnum gameRule) { + super(gameRule.getTranslationKey() + ".name", gameRule.getTranslationKey() + ".desc"); + + this.gameRule = gameRule; + this.button = new CycleButtonElement<>(0, 0, 0, 150, 20, gameRule.getValues(), gameRule.getDefaultValue(), this::translateValue); + } + + public void setGameRuleCollection(final @NotNull GameRuleCollection collection) { + this.gameRuleCollection = collection; + } + + private @NotNull String translateValue(final @NotNull E value) { + return I18n.getInstance().translateKey(this.gameRule.getTranslationKey() + ".value." + value.name().toLowerCase(Locale.ROOT)); + } + + @Override + public void resetValue() { + assert this.gameRuleCollection != null; + this.gameRuleCollection.setValue(this.gameRule, this.gameRule.getDefaultValue()); + this.onChange(); + } + + @Override + public void init(final @NotNull Minecraft mc){ + this.onChange(); + } + + @Override + public boolean isDefault() { + assert this.gameRuleCollection != null; + return this.gameRuleCollection.getValue(this.gameRule).equals(this.gameRule.getDefaultValue()); + } + + @Override + protected void buttonClicked(final int mouseButton, final int x, final int y, final int width, final int height, final int relativeMouseX, final int relativeMouseY) { + assert this.gameRuleCollection != null; + this.gameRuleCollection.setValue(this.gameRule, this.button.cycle()); + } + + protected void onChange() { + assert this.gameRuleCollection != null; + this.button.setValue(this.gameRuleCollection.getValue(this.gameRule)); + } + + @Override + protected void renderButton(final int x, final int y, final int relativeButtonX, final int relativeButtonY, final int buttonWidth, final int buttonHeight, final int relativeMouseX, final int relativeMouseY) { + super.renderButton(x, y, relativeButtonX, relativeButtonY, buttonWidth, buttonHeight, relativeMouseX, relativeMouseY); + + this.button.xPosition = x + relativeButtonX; + this.button.yPosition = y + relativeButtonY; + this.button.width = buttonWidth; + this.button.height = buttonHeight; + + this.button.drawButton(mc, x + relativeMouseX, y + relativeMouseY); + + if (mc.currentScreen != null && relativeMouseX >= relativeButtonX && relativeMouseX < relativeButtonX + buttonWidth && relativeMouseY >= relativeButtonY && relativeButtonY < relativeButtonY + buttonHeight) { + mc.currentScreen.setDesiredCursor(CursorShape.HAND); + } + } +} diff --git a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java index 263d8f18f..83c596db1 100644 --- a/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java +++ b/game/client/src/main/java/net/minecraft/client/render/block/model/BlockModelWireRedstone.java @@ -13,8 +13,6 @@ import net.minecraft.core.world.pos.TilePos; import net.minecraft.core.world.pos.TilePosc; import org.jetbrains.annotations.NotNull; -import static net.minecraft.core.block.BlockLogicWireRedstone.isClimbableWall; - public class BlockModelWireRedstone extends BlockModelStandard { protected final IconCoordinate wireStraight = TextureRegistry.getTexture("minecraft:block/wire_redstone_straight"); protected final IconCoordinate wireCross = TextureRegistry.getTexture("minecraft:block/wire_redstone_cross"); @@ -42,31 +40,19 @@ public class BlockModelWireRedstone extends BlockModelStan tessellator.setLightmapCoord2i(Math.max(worldSource.getSavedLightValue(LightLayer.Block, tilePos), meta & 0xF), worldSource.getSavedLightValue(LightLayer.Sky, tilePos)); tessellator.setColorOpaque3f(red, green, blue); - boolean west = BlockLogicWireRedstone.shouldConnectTo(worldSource, tilePos.west(queryPos), Side.WEST) || !isClimbableWall(worldSource, tilePos.west(queryPos), Side.WEST) && BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(-1, -1, 0, queryPos), Side.WEST, Side.BOTTOM); - boolean east = BlockLogicWireRedstone.shouldConnectTo(worldSource, tilePos.east(queryPos), Side.EAST) || !isClimbableWall(worldSource, tilePos.east(queryPos), Side.EAST) && BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(1, -1, 0, queryPos), Side.EAST, Side.BOTTOM); - boolean north = BlockLogicWireRedstone.shouldConnectTo(worldSource, tilePos.north(queryPos), Side.NORTH) || !isClimbableWall(worldSource, tilePos.north(queryPos), Side.NORTH) && BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(0, -1, -1, queryPos), Side.NORTH, Side.BOTTOM); - boolean south = BlockLogicWireRedstone.shouldConnectTo(worldSource, tilePos.south(queryPos), Side.SOUTH) || !isClimbableWall(worldSource, tilePos.south(queryPos), Side.SOUTH) && BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(0, -1, 1, queryPos), Side.SOUTH, Side.BOTTOM); + boolean west = BlockLogicWireRedstone.shouldConnectToSide(worldSource, tilePos, Side.WEST); + boolean east = BlockLogicWireRedstone.shouldConnectToSide(worldSource, tilePos, Side.EAST); + boolean north = BlockLogicWireRedstone.shouldConnectToSide(worldSource, tilePos, Side.NORTH); + boolean south = BlockLogicWireRedstone.shouldConnectToSide(worldSource, tilePos, Side.SOUTH); boolean westUp = false; boolean eastUp = false; boolean northUp = false; boolean southUp = false; if (!worldSource.isBlockOpaqueCube(tilePos.up(queryPos))) { - if (BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(-1, 1, 0, queryPos), Side.WEST, Side.TOP)) { - west = true; - westUp = true; - } - if (BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(1, 1, 0, queryPos), Side.EAST, Side.TOP)) { - east = true; - eastUp = true; - } - if (BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(0, 1, -1, queryPos), Side.NORTH, Side.TOP)) { - north = true; - northUp = true; - } - if (BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(0, 1, 1, queryPos), Side.SOUTH, Side.TOP)) { - south = true; - southUp = true; - } + westUp = BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(-1, 1, 0, queryPos), Side.WEST, Side.TOP); + eastUp = BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(1, 1, 0, queryPos), Side.EAST, Side.TOP); + northUp = BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(0, 1, -1, queryPos), Side.NORTH, Side.TOP); + southUp = BlockLogicWireRedstone.shouldConnectToDiagonal(worldSource, tilePos.add(0, 1, 1, queryPos), Side.SOUTH, Side.TOP); } final int x = tilePos.x(); diff --git a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java index 0e30bd73c..34143c39a 100644 --- a/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java +++ b/game/client/src/main/java/net/minecraft/client/render/item/model/ItemModelStandard.java @@ -38,7 +38,7 @@ public class ItemModelStandard extends ItemModel{ public static final DisplayPos DEFAULT_ITEM_THIRD_PERSON_RIGHT_HAND = new DisplayPos(0, 3/16f, 1/16f, 0, 0, 0, 0.55f, 0.55f, 0.55f); public static final DisplayPos DEFAULT_ITEM_THIRD_PERSON_LEFT_HAND = new DisplayPos(0, 3/16f, 1/16f, 0, 0, 0, 0.55f, 0.55f, 0.55f); public static final DisplayPos DEFAULT_ITEM_FIRST_PERSON_RIGHT_HAND = new DisplayPos(1.13f/16f, 3.2f/16f, 1.13f/16f, 0, -90, 25, 0.68f, 0.68f, 0.68f); - public static final DisplayPos DEFAULT_ITEM_FIRST_PERSON_LEFT_HAND = new DisplayPos(1.13f/16f, 3.2f/16f, 1.13f/16f, 0, -90, 25, 0.68f, 0.68f, 0.68f); + public static final DisplayPos DEFAULT_ITEM_FIRST_PERSON_LEFT_HAND = new DisplayPos(1.13f/16f, 3.2f/16f, 1.13f/16f, 0, 90, -25, 0.68f, 0.68f, 0.68f); public static final DisplayPos DEFAULT_ITEM_FIXED = new DisplayPos(0, 0, 0, 0, 180, 0, 1, 1, 1); protected boolean itemfullBright = false; // TODO this is probably redundant with the emissive textures now diff --git a/game/client/src/main/resources/assets/minecraft/models/block/stairs.json b/game/client/src/main/resources/assets/minecraft/models/block/stairs.json index 886682db1..0719965bd 100644 --- a/game/client/src/main/resources/assets/minecraft/models/block/stairs.json +++ b/game/client/src/main/resources/assets/minecraft/models/block/stairs.json @@ -10,10 +10,25 @@ "translation": [ 0, 0, 0 ], "scale": [ 1, 1, 1 ] }, + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [ 0, 2.5, 0], + "scale": [ 0.375, 0.375, 0.375 ] + }, + "firstperson_righthand": { + "rotation": [ 0, 45, 0 ], + "translation": [ 0, 0, 0 ], + "scale": [0.4, 0.4, 0.4] + }, "thirdperson_lefthand": { - "rotation": [ 75, -135, 0 ], + "rotation": [75, -135, 0], "translation": [ 0, 2.5, 0], "scale": [ 0.375, 0.375, 0.375 ] + }, + "firstperson_lefthand": { + "rotation": [ 0, -135, 0 ], + "translation": [ 0, 0, 0 ], + "scale": [0.4, 0.4, 0.4] } }, "textures": { diff --git a/game/client/src/main/resources/credits.txt b/game/client/src/main/resources/credits.txt index 78a297d84..cef07c221 100644 --- a/game/client/src/main/resources/credits.txt +++ b/game/client/src/main/resources/credits.txt @@ -53,6 +53,7 @@ Doop (@brokendoop) --Gloomstone bricks --Sorched Logs --Crude steel texture +--Statue item textures Gungun974 --Improved packet processing --Bug fixes diff --git a/game/core/src/main/java/net/minecraft/core/block/Block.java b/game/core/src/main/java/net/minecraft/core/block/Block.java index 3880df35b..348e74da5 100644 --- a/game/core/src/main/java/net/minecraft/core/block/Block.java +++ b/game/core/src/main/java/net/minecraft/core/block/Block.java @@ -401,6 +401,11 @@ public final class Block this.logic.onNeighborChanged(world, tilePos, block); } + @Override + public void onChunkLoad(@NotNull World world, @NotNull TilePosc tilePos) { + this.logic.onChunkLoad(world, tilePos); + } + @Override public int tickDelay() { return this.logic.tickDelay(); diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java index a259c11c0..b2384a9c4 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockInterface.java @@ -159,6 +159,8 @@ interface BlockInterface { void onNeighborChanged(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Block block); + void onChunkLoad(final @NotNull World world, final @NotNull TilePosc tilePos); + @Deprecated default void onNeighborBlockChange(final @NotNull World world, final int x, final int y, final int z, final int id) { this.onNeighborChanged(world, new TilePos(x, y, z), Objects.requireNonNull(Blocks.getBlock(id))); diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java index 05e590e5b..72098243e 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogic.java @@ -203,6 +203,9 @@ public class BlockLogic implements BlockInterface, IItemConvertible { @Override public void onNeighborChanged(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Block block) { } + @Override + public void onChunkLoad(final @NotNull World world, final @NotNull TilePosc tilePos) { } + @Override public int tickDelay() { return 10; diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java index 7571fabb6..36c0730cb 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicFire.java @@ -8,6 +8,8 @@ import net.minecraft.core.block.tag.BlockTags; import net.minecraft.core.data.gamerule.GameRules; import net.minecraft.core.data.tag.Tag; import net.minecraft.core.entity.Entity; +import net.minecraft.core.enums.EnumFireSpread; +import net.minecraft.core.item.block.ItemBlock; import net.minecraft.core.sound.SoundCategory; import net.minecraft.core.util.helper.Side; import net.minecraft.core.util.phys.BoundingVolume; @@ -250,8 +252,10 @@ public class BlockLogicFire } world.scheduleBlockUpdate(tilePos, this.block, this.tickDelay()); + final EnumFireSpread spreadRule = world.getGameRuleValue(GameRules.FIRE_SPREAD); + final boolean doFireBurn = world.getGameRuleValue(GameRules.DO_FIRE_BURN); - if (!infiniBurn && !this.canNeighborCatchFire(world, tilePos)) { + if (!infiniBurn && (!doFireBurn || !this.canNeighborCatchFire(world, tilePos))) { if (!world.isBlockNormalCube(tilePos.down(queryPos)) || meta > 3) { this.setBurnResult(world, tilePos); } @@ -263,12 +267,18 @@ public class BlockLogicFire return; } - this.checkBurn(world, tilePos.east(queryPos), 300, rand, meta); - this.checkBurn(world, tilePos.west(queryPos), 300, rand, meta); - this.checkBurn(world, tilePos.down(queryPos), 250, rand, meta); - this.checkBurn(world, tilePos.up(queryPos), 250, rand, meta); - this.checkBurn(world, tilePos.north(queryPos), 300, rand, meta); - this.checkBurn(world, tilePos.south(queryPos), 300, rand, meta); + if (doFireBurn) { + this.checkBurn(world, tilePos.east(queryPos), 300, rand, meta, spreadRule); + this.checkBurn(world, tilePos.west(queryPos), 300, rand, meta, spreadRule); + this.checkBurn(world, tilePos.down(queryPos), 250, rand, meta, spreadRule); + this.checkBurn(world, tilePos.up(queryPos), 250, rand, meta, spreadRule); + this.checkBurn(world, tilePos.north(queryPos), 300, rand, meta, spreadRule); + this.checkBurn(world, tilePos.south(queryPos), 300, rand, meta, spreadRule); + } + + if (spreadRule == EnumFireSpread.NONE) { + return; + } final @NotNull TilePos localPos = new TilePos(tilePos); for (localPos.x = tilePos.x() - 1; localPos.x <= tilePos.x() + 1; localPos.x++) { @@ -282,7 +292,7 @@ public class BlockLogicFire if (localPos.y > tilePos.y() + 1) { a += (localPos.y - (tilePos.y() + 1)) * 100; } - final int b = this.getFireChance(world, localPos); + final int b = this.getFireChance(world, localPos, spreadRule); if (b <= 0) { continue; } @@ -298,7 +308,7 @@ public class BlockLogicFire continue; } - if (world.getGameRuleValue(GameRules.DO_FIRE_SPREAD) && this.getBurnResult(world, localPos) == Blocks.AIR /* Fix for fire destroying moss blocks */) { + if (this.getBurnResult(world, localPos) == Blocks.AIR /* Fix for fire destroying moss blocks */) { //Spread Fire with higher meta world.setBlockTypeDataNotify(localPos, this.getSpreadFireBlock(), Math.min(meta + rand.nextInt(5) / 4, 15));} } @@ -306,10 +316,10 @@ public class BlockLogicFire } } - private void checkBurn(final @NotNull World world, final @NotNull TilePos tilePos, final int chance, final @NotNull Random random, final int meta) { - if (!world.getGameRuleValue(GameRules.DO_FIRE_SPREAD)) return; + private void checkBurn(final @NotNull World world, final @NotNull TilePos tilePos, final int chance, final @NotNull Random random, final int meta, final @NotNull EnumFireSpread spreadRule) { if (random.nextInt(chance) < burnChance[world.getBlockType(tilePos).id()]) { final Block targetBlock = world.getBlockType(tilePos); + if (spreadRule == EnumFireSpread.FOLIAGE && !isFoliage(targetBlock)) return; final boolean isTNT = targetBlock == Blocks.TNT; // Logs should always scorch when they burn, never convert into a fire block first. @@ -319,7 +329,7 @@ public class BlockLogicFire return; } - if (random.nextInt(meta + 10) < 5 && !world.isBlockBeingRainedOn(tilePos)) { + if (spreadRule != EnumFireSpread.NONE && random.nextInt(meta + 10) < 5 && !world.isBlockBeingRainedOn(tilePos)) { if (this.getBurnResult(world, tilePos) == Blocks.AIR /* Fix for fire destroying moss blocks */) { //Spread Fire with higher meta world.setBlockTypeDataNotify(tilePos, this.getSpreadFireBlock(), Math.min(meta + random.nextInt(5) / 4, 15)); @@ -391,18 +401,18 @@ public class BlockLogicFire return canBurn(world, tilePos.south(queryPos)); } - private int getFireChance(final @NotNull World world, final @NotNull TilePosc tilePos) { + private int getFireChance(final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull EnumFireSpread spreadRule) { int flammability = 0; if (!world.isAirBlock(tilePos)) { return 0; } else { TilePos queryPos = new TilePos(); - flammability = getFlammability(world, tilePos.east(queryPos), flammability); - flammability = getFlammability(world, tilePos.west(queryPos), flammability); - flammability = getFlammability(world, tilePos.down(queryPos), flammability); - flammability = getFlammability(world, tilePos.up(queryPos), flammability); - flammability = getFlammability(world, tilePos.north(queryPos), flammability); - flammability = getFlammability(world, tilePos.south(queryPos), flammability); + flammability = getFlammability(world, tilePos.east(queryPos), flammability, spreadRule); + flammability = getFlammability(world, tilePos.west(queryPos), flammability, spreadRule); + flammability = getFlammability(world, tilePos.down(queryPos), flammability, spreadRule); + flammability = getFlammability(world, tilePos.up(queryPos), flammability, spreadRule); + flammability = getFlammability(world, tilePos.north(queryPos), flammability, spreadRule); + flammability = getFlammability(world, tilePos.south(queryPos), flammability, spreadRule); return flammability; } } @@ -415,11 +425,23 @@ public class BlockLogicFire return flameChance[blockId] > 0; } + public static boolean isFoliage(final @NotNull Block block) { + final BlockLogic logic = block.getLogic(); + return logic instanceof BlockLogicLog || logic instanceof BlockLogicLeavesBase || logic instanceof BlockLogicMoss; + } + public static int getFlammability(final @NotNull World world, final @NotNull TilePosc tilePos, final int currentFlameChance) { final int blockFlameChance = flameChance[world.getBlockType(tilePos).id()]; return Math.max(blockFlameChance, currentFlameChance); } + public static int getFlammability(final @NotNull World world, final @NotNull TilePosc tilePos, final int currentFlameChance, final @NotNull EnumFireSpread spreadRule) { + if (spreadRule == EnumFireSpread.FOLIAGE && !isFoliage(world.getBlockType(tilePos))) { + return currentFlameChance; + } + return getFlammability(world, tilePos, currentFlameChance); + } + public boolean isValidFireLocation(final @NotNull World world, final @NotNull TilePosc tilePos) { return world.isBlockNormalCube(tilePos.down(new TilePos())) || this.canNeighborCatchFire(world, tilePos); } diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java index 6c3a6c0b6..3037261c6 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicPortal.java @@ -321,13 +321,7 @@ public class BlockLogicPortal extends BlockLogicTransparent implements IPainted, } } } - if (entity instanceof Player ridingPlayer && ridingPlayer.vehicle instanceof MobPig) { - ridingPlayer.handlePortal(this.block.id(), getColor(world, tilePos)); - } else if (entity instanceof MobPig && entity.passenger instanceof Player riderPlayer) { - riderPlayer.handlePortal(this.block.id(), getColor(world, tilePos)); - } else if (entity.vehicle == null && entity.passenger == null) { - entity.handlePortal(this.block.id(), getColor(world, tilePos)); - } + entity.handlePortal(this.block.id(), getColor(world, tilePos)); } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorchRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorchRedstone.java index 5196b9ec6..f12ce32fe 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorchRedstone.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicTorchRedstone.java @@ -70,6 +70,7 @@ public class BlockLogicTorchRedstone extends BlockLogicTorch { @Override public void updateTick(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Random rand, boolean isRandomTick) { + if (isRandomTick || world.isClientSide) return; boolean isPowered = hasNeighborSignal(world, tilePos); if (this.torchActive) { if (isPowered) { @@ -80,10 +81,17 @@ public class BlockLogicTorchRedstone extends BlockLogicTorch { } } + @Override + public void onChunkLoad(@NotNull World world, @NotNull TilePosc tilePos) { + world.scheduleBlockUpdate(tilePos, this.block, tickDelay()); + } + @Override public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block block) { super.onNeighborChanged(world, tilePos, block); - world.scheduleBlockUpdate(tilePos, this.block, tickDelay()); + if (this.torchActive == hasNeighborSignal(world, tilePos)) { + world.scheduleBlockUpdate(tilePos, this.block, tickDelay()); + } } @Override diff --git a/game/core/src/main/java/net/minecraft/core/block/BlockLogicWireRedstone.java b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWireRedstone.java index 65755d6a8..e9df3967f 100644 --- a/game/core/src/main/java/net/minecraft/core/block/BlockLogicWireRedstone.java +++ b/game/core/src/main/java/net/minecraft/core/block/BlockLogicWireRedstone.java @@ -317,37 +317,10 @@ public class BlockLogicWireRedstone extends BlockLogic implements ISupportable, return true; } - TilePos queryPos = new TilePos(); - boolean negXShouldConnectTo = - shouldConnectTo(source, tilePos.add(-1, 0, 0, queryPos), Side.WEST) || - shouldConnectToDiagonal(source, tilePos.add(-1, -1, 0, queryPos), Side.WEST, Side.BOTTOM); - - boolean posXShouldConnectTo = - shouldConnectTo(source, tilePos.add(1, 0, 0, queryPos), Side.EAST) || - shouldConnectToDiagonal(source, tilePos.add(1, -1, 0, queryPos), Side.EAST, Side.BOTTOM); - - boolean negZShouldConnectTo = - shouldConnectTo(source, tilePos.add(0, 0, -1, queryPos), Side.NORTH) || - shouldConnectToDiagonal(source, tilePos.add(0, -1, -1, queryPos), Side.NORTH, Side.BOTTOM); - - boolean posZShouldConnectTo = - shouldConnectTo(source, tilePos.add(0, 0, 1, queryPos), Side.SOUTH) || - shouldConnectToDiagonal(source, tilePos.add(0, -1, 1, queryPos), Side.SOUTH, Side.BOTTOM); - - if (!source.isBlockNormalCube(tilePos.up(queryPos))) { - if (isClimbableWall(source, tilePos.add(-1, 0, 0, queryPos), Side.WEST) && - shouldConnectToDiagonal(source, tilePos.add(-1, 1, 0, queryPos), Side.WEST, Side.TOP)) - {negXShouldConnectTo = true;} - if (isClimbableWall(source, tilePos.add(1, 0, 0, queryPos), Side.EAST) && - shouldConnectToDiagonal(source, tilePos.add(1, 1, 0, queryPos), Side.EAST, Side.TOP)) - {posXShouldConnectTo = true;} - if (isClimbableWall(source, tilePos.add(0, 0, -1, queryPos), Side.NORTH) && - shouldConnectToDiagonal(source, tilePos.add(0, 1, -1, queryPos), Side.NORTH, Side.TOP)) - {negZShouldConnectTo = true;} - if (isClimbableWall(source, tilePos.add(0, 0, 1, queryPos), Side.SOUTH) && - shouldConnectToDiagonal(source, tilePos.add(0, 1, 1, queryPos), Side.SOUTH, Side.TOP)) - {posZShouldConnectTo = true;} - } + boolean negXShouldConnectTo = shouldConnectToSide(source, tilePos, Side.WEST); + boolean posXShouldConnectTo = shouldConnectToSide(source, tilePos, Side.EAST); + boolean negZShouldConnectTo = shouldConnectToSide(source, tilePos, Side.NORTH); + boolean posZShouldConnectTo = shouldConnectToSide(source, tilePos, Side.SOUTH); // Make wire emit block updates when a redirection happens if (source instanceof World world) { int direction = (data & MASK_DIRECTION) >> 4; // 0b00000000 00000000 00000000 DDDD0000 @@ -442,6 +415,19 @@ public class BlockLogicWireRedstone extends BlockLogic implements ISupportable, return shouldConnectToDiagonal(worldSource, new TilePos(x, y, z), side1, side2); } + public static boolean shouldConnectToSide(@NotNull WorldSource source, @NotNull TilePosc wirePos, @NotNull Side side) { + TilePos adjacentPos = wirePos.add(side.direction(), new TilePos()); + if (shouldConnectTo(source, adjacentPos, side)) { + return true; + } + if (!isClimbableWall(source, adjacentPos, side) && + shouldConnectToDiagonal(source, adjacentPos.down(new TilePos()), side, Side.BOTTOM)) { + return true; + } + return !source.isBlockOpaqueCube(wirePos.up(new TilePos())) && + shouldConnectToDiagonal(source, adjacentPos.up(new TilePos()), side, Side.TOP); + } + public static boolean shouldConnectToDiagonal(@NotNull WorldSource worldSource, @NotNull TilePos tilePos, @NotNull Side side1, @NotNull Side side2) { if (!(side2 == Side.TOP || side2 == Side.BOTTOM)) return false; // Maybe some can generate a connection if placed below a block in the future? diff --git a/game/core/src/main/java/net/minecraft/core/block/FluidHardening.java b/game/core/src/main/java/net/minecraft/core/block/FluidHardening.java index 2e6e82020..74ea6f569 100644 --- a/game/core/src/main/java/net/minecraft/core/block/FluidHardening.java +++ b/game/core/src/main/java/net/minecraft/core/block/FluidHardening.java @@ -5,6 +5,7 @@ import net.minecraft.core.block.material.Material; import net.minecraft.core.block.material.Materials; import net.minecraft.core.entity.player.Player; import net.minecraft.core.world.World; +import net.minecraft.core.world.pos.TilePos; import net.minecraft.core.world.pos.TilePosc; import net.minecraft.core.world.type.tag.WorldTypeTags; import org.jetbrains.annotations.NotNull; @@ -48,6 +49,9 @@ public final class FluidHardening { } private static boolean hardenWaterWithLava(final @NotNull World world, final @NotNull TilePosc tilePos) { + if (world.getBlockMaterial(tilePos.up(new TilePos())) != Materials.LAVA) { + return false; + } final int data = world.getBlockData(tilePos) & 0x0F; if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) { world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.OBSIDIAN : Blocks.COBBLE_GLOOMSTONE); @@ -59,6 +63,9 @@ public final class FluidHardening { } private static boolean hardenWaterWithAcid(final @NotNull World world, final @NotNull TilePosc tilePos) { + if (world.getBlockMaterial(tilePos.up(new TilePos())) != Materials.ACID) { + return false; + } final int data = world.getBlockData(tilePos) & 0x0F; if (world.getWorldType().hasTag(WorldTypeTags.NETHER)) { world.setBlockTypeNotify(tilePos, data == 0 ? Blocks.OBSIDIAN : Blocks.GLOOMSTONE); 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 356b23d54..4e08fd416 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 @@ -3,6 +3,7 @@ package net.minecraft.core.block; import net.minecraft.core.block.material.Material; import net.minecraft.core.block.material.Materials; import net.minecraft.core.data.gamerule.GameRules; +import net.minecraft.core.enums.EnumFireSpread; import net.minecraft.core.world.World; import net.minecraft.core.world.pos.TilePos; import net.minecraft.core.world.pos.TilePosc; @@ -50,7 +51,7 @@ public class FluidLava @Override public void updateTickStill(final @NotNull BlockLogicFluid logicFluid, final @NotNull World world, final @NotNull TilePosc tilePos, final @NotNull Random rand) { - if (!world.getGameRuleValue(GameRules.DO_FIRE_SPREAD)) return; + if (world.getGameRuleValue(GameRules.FIRE_SPREAD) == EnumFireSpread.NONE) return; TilePos p = new TilePos(tilePos); TilePos queryPos = new TilePos(tilePos); final int count = rand.nextInt(3); diff --git a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java index ee783315d..b8d6d4ae1 100644 --- a/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java +++ b/game/core/src/main/java/net/minecraft/core/block/piston/BlockLogicPistonBase.java @@ -33,8 +33,6 @@ import org.joml.Vector3d; import org.joml.primitives.AABBd; import org.joml.primitives.AABBdc; -import java.util.Random; - import static net.minecraft.core.block.piston.PistonCommon.*; public class BlockLogicPistonBase extends BlockLogic implements BlockLogic.MatcherDataEquivalency.Masked { @@ -426,22 +424,11 @@ public class BlockLogicPistonBase extends BlockLogic implements BlockLogic.Match this.signalUpdate(world, tilePos); } - @Override - public void updateTick(@NotNull World world, @NotNull TilePosc tilePos, @NotNull Random rand, boolean isRandomTick) { - if (isRandomTick || world.isClientSide) return; - this.signalUpdate(world, tilePos); - } - @Override public void onNeighborChanged(@NotNull World world, @NotNull TilePosc tilePos, final @NotNull Block block) { if (world.isClientSide) return; - final int data = fixLegacyBaseData(world, tilePos); - - final boolean powered = hasNeighborSignal(world, tilePos, Direction.fromId(DIRECTION.get(data))); - final boolean extended = IS_EXTENDED.bool(data); - if (powered != extended) { - world.scheduleBlockUpdate(tilePos, this.block, 1); - } + final var data = fixLegacyBaseData(world, tilePos); + this.signalUpdate(world, tilePos, data); } @Override diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java index 2f6d3f82e..c0f4669d3 100644 --- a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java +++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRule.java @@ -8,12 +8,19 @@ public abstract class GameRule private final @NotNull String key; private final @NotNull String translationKey; private final T defaultValue; + private final @NotNull String valueArgumentName; public GameRule(final @NotNull String key, final @NotNull String translationKey, final @NotNull T defaultValue) + { + this(key, translationKey, defaultValue, "value"); + } + + public GameRule(final @NotNull String key, final @NotNull String translationKey, final @NotNull T defaultValue, final @NotNull String valueArgumentName) { this.key = key; this.translationKey = translationKey; this.defaultValue = defaultValue; + this.valueArgumentName = valueArgumentName; } public @NotNull String getKey() @@ -30,6 +37,11 @@ public abstract class GameRule return this.defaultValue; } + public @NotNull String getValueArgumentName() + { + return this.valueArgumentName; + } + public abstract void writeToNBT(@NotNull CompoundTag tag, T value); public abstract T readFromNBT(@NotNull CompoundTag tag); diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java index daa8264c9..32c2bf57f 100644 --- a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java +++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleCollection.java @@ -2,6 +2,7 @@ package net.minecraft.core.data.gamerule; import com.mojang.nbt.tags.CompoundTag; import net.minecraft.core.data.registry.Registries; +import net.minecraft.core.enums.EnumFireSpread; import net.minecraft.core.world.settings.WorldConfiguration; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -85,9 +86,21 @@ public final class GameRuleCollection collection.setValue((GameRule)gameRule, gameRule.readFromNBT(tag)); } + applyLegacyConversions(tag, collection); + return collection; } + private static void applyLegacyConversions(final @NotNull CompoundTag tag, final @NotNull GameRuleCollection collection) + { + if (tag.containsKey("doFireSpread") && !tag.containsKey("fireSpread")) + { + final boolean legacyFireSpread = tag.getBoolean("doFireSpread"); + collection.setValue(GameRules.FIRE_SPREAD, legacyFireSpread ? EnumFireSpread.ALL : EnumFireSpread.NONE); + collection.setValue(GameRules.DO_FIRE_BURN, legacyFireSpread); + } + } + public static void writeToNBT(CompoundTag tag, GameRuleCollection collection) { for (GameRule gameRule : Registries.GAME_RULES) diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleEnum.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleEnum.java new file mode 100644 index 000000000..7cf649f35 --- /dev/null +++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleEnum.java @@ -0,0 +1,51 @@ +package net.minecraft.core.data.gamerule; + +import com.mojang.nbt.tags.CompoundTag; +import com.mojang.nbt.tags.StringTag; +import com.mojang.nbt.tags.Tag; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; + +public class GameRuleEnum> extends GameRule { + private final E @NotNull [] values; + + public GameRuleEnum(final String key, final String translationKey, final @NotNull E defaultValue) { + super(key, translationKey, defaultValue); + this.values = defaultValue.getDeclaringClass().getEnumConstants(); + } + + public E @NotNull [] getValues() { + return this.values; + } + + @Override + public void writeToNBT(final @NotNull CompoundTag tag, final @NotNull E value) { + tag.put(getKey(), new StringTag(value.name().toLowerCase(Locale.ROOT))); + } + + @Override + public E readFromNBT(final @NotNull CompoundTag tag) { + final Tag ruleTag = tag.getTag(getKey()); + if (ruleTag instanceof StringTag) { + final E value = this.parseFromString(((StringTag) ruleTag).getValue()); + if (value != null) { + return value; + } + } + + return getDefaultValue(); + } + + @Override + public @Nullable E parseFromString(final @NotNull String string) { + for (final E value : this.values) { + if (value.name().equalsIgnoreCase(string)) { + return value; + } + } + + return null; + } +} diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleInteger.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleInteger.java index 80a9bfe31..56606b1b4 100644 --- a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleInteger.java +++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRuleInteger.java @@ -10,6 +10,10 @@ public class GameRuleInteger extends GameRule { super(key, translationKey, defaultValue); } + public GameRuleInteger(final String key, final String translationKey, final Integer defaultValue, final String valueArgumentName) { + super(key, translationKey, defaultValue, valueArgumentName); + } + @Override public void writeToNBT(final @NotNull CompoundTag tag, final Integer value) { final IntTag ruleTag = new IntTag(value); diff --git a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRules.java b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRules.java index 509fb9c7f..e9701aed0 100644 --- a/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRules.java +++ b/game/core/src/main/java/net/minecraft/core/data/gamerule/GameRules.java @@ -1,7 +1,8 @@ package net.minecraft.core.data.gamerule; import net.minecraft.core.data.registry.Registries; -import net.minecraft.core.entity.Entity; +import net.minecraft.core.enums.EnumFireSpread; +import org.jetbrains.annotations.NotNull; public abstract class GameRules { @@ -12,17 +13,19 @@ public abstract class GameRules public static GameRuleBoolean DO_SEASONAL_GROWTH = register(new GameRuleBoolean("doSeasonalGrowth", "gamerule.do_seasonal_growth", true)); public static GameRuleBoolean TREECAPITATOR = register(new GameRuleBoolean("treecapitator", "gamerule.treecapitator", false)); public static GameRuleBoolean DWARF_MODE = register(new GameRuleBoolean("dwarfMode", "gamerule.dwarf_mode", false)); - public static GameRuleBoolean MOB_GRIEFING = register(new GameRuleBoolean("mobGriefing", "gamerule.mob_griefing", true)); + public static GameRuleBoolean DO_MOB_GRIEFING = register(new GameRuleBoolean("doMobGriefing", "gamerule.do_mob_griefing", true)); + public static GameRuleBoolean DO_EXPLOSION_GRIEFING = register(new GameRuleBoolean("doExplosionGriefing", "gamerule.do_explosion_griefing", true)); public static GameRuleBoolean DO_DAY_CYCLE = register(new GameRuleBoolean("doDaylightCycle", "gamerule.do_day_night_cycle", true)); public static GameRuleBoolean DO_WEATHER_CYCLE = register(new GameRuleBoolean("doWeatherCycle", "gamerule.do_weather_cycle", true)); - public static GameRuleBoolean DO_FIRE_SPREAD = register(new GameRuleBoolean("doFireSpread", "gamerule.do_fire_spread", true)); - public static GameRuleBoolean INSTANT_HEALING = register(new GameRuleBoolean("instantHealing", "gamerule.instant_healing", false)); - public static GameRuleInteger ACID_MELT_RATE = register(new GameRuleInteger("acidMeltRate", "gamerule.acid_melt_rate", Entity.FIRE_DAMAGE_INTERVAL_TICKS)); + public static GameRuleEnum FIRE_SPREAD = register(new GameRuleEnum<>("fireSpread", "gamerule.fire_spread", EnumFireSpread.ALL)); + public static GameRuleBoolean DO_FIRE_BURN = register(new GameRuleBoolean("doFireBurn", "gamerule.do_fire_burn", true)); + public static GameRuleBoolean DO_LIGHTNING_BURN = register(new GameRuleBoolean("doLightningBurn", "gamerule.do_lightning_burn", true)); + public static GameRuleBoolean DO_INSTANT_HEALING = register(new GameRuleBoolean("doInstantHealing", "gamerule.do_instant_healing", false)); public static GameRuleInteger RANDOM_TICK_SPEED = register(new GameRuleInteger("randomTickSpeed", "gamerule.random_tick_speed", 4)); - public static GameRuleInteger ITEM_DESPAWN_DELAY = register(new GameRuleInteger("itemDespawnDelay", "gamerule.item_despawn_delay", 12000)); - public static GameRuleInteger DROPPED_ITEM_DESPAWN_DELAY = register(new GameRuleInteger("droppedItemDespawnDelay", "gamerule.dropped_item_despawn_delay", 12000)); + public static GameRuleInteger ITEM_DESPAWN_DELAY = register(new GameRuleInteger("itemDespawnDelay", "gamerule.item_despawn_delay", 600, "seconds")); + public static GameRuleInteger PLAYER_ITEM_DESPAWN_DELAY = register(new GameRuleInteger("playerItemDespawnDelay", "gamerule.player_item_despawn_delay", 720, "seconds")); - public static > T register(T gameRule) + public static > @NotNull T register(T gameRule) { Registries.GAME_RULES.register(gameRule.getKey(), gameRule); diff --git a/game/core/src/main/java/net/minecraft/core/entity/Entity.java b/game/core/src/main/java/net/minecraft/core/entity/Entity.java index 51a312c6d..cde2b08d2 100644 --- a/game/core/src/main/java/net/minecraft/core/entity/Entity.java +++ b/game/core/src/main/java/net/minecraft/core/entity/Entity.java @@ -12,7 +12,6 @@ import net.minecraft.core.block.material.Material; import net.minecraft.core.block.material.Materials; import net.minecraft.core.block.piston.BlockLogicPistonHead; import net.minecraft.core.block.tag.BlockTags; -import net.minecraft.core.data.gamerule.GameRules; import net.minecraft.core.entity.animal.MobPig; import net.minecraft.core.entity.player.Player; import net.minecraft.core.entity.vehicle.EntityBoat; @@ -698,13 +697,11 @@ public abstract class Entity int maxY = MathHelper.floor(this.bb.maxY - 0.001D); int maxZ = MathHelper.floor(this.bb.maxZ - 0.001D); if (this.world.areBlocksLoaded(minX, minY, minZ, maxX, maxY, maxZ)) { - for (int _x = minX; _x <= maxX; _x++) { - for (int _y = minY; _y <= maxY; _y++) { - for (int _z = minZ; _z <= maxZ; _z++) { - int blockId = this.world.getBlockId(_x, _y, _z); - if (blockId > 0) { - Blocks.blocksList[blockId].onEntityCollidedWithBlock(this.world, _x, _y, _z, this); - } + TilePos queryPos = new TilePos(); + for (queryPos.x = minX; queryPos.x <= maxX; queryPos.x++) { + for (queryPos.y = minY; queryPos.y <= maxY; queryPos.y++) { + for (queryPos.z = minZ; queryPos.z <= maxZ; queryPos.z++) { + this.world.getBlockType(queryPos).onEntityCollision(this.world, queryPos, this); } } @@ -799,8 +796,7 @@ public abstract class Entity public void acidTick() { final boolean physicallyInAcid = isInAcid(); - final int meltRate = Math.max(1, this.world.getGameRuleValue(GameRules.ACID_MELT_RATE)); - final boolean shouldTickRate = (this.tickCount % meltRate == 0); + final boolean shouldTickRate = (this.tickCount % FIRE_DAMAGE_INTERVAL_TICKS == 0); if (physicallyInAcid) { this.acidExitDelayLeft = ACID_EXIT_BUFFER; diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java b/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java index 9e292b369..8ff78129c 100644 --- a/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java +++ b/game/core/src/main/java/net/minecraft/core/entity/EntityItem.java @@ -83,7 +83,7 @@ public class EntityItem extends Entity this.xd = (float)(Math.random() * 0.2D - 0.1D); this.yd = 0.2D; this.zd = (float)(Math.random() * 0.2D - 0.1D); - this.lifetime = world.getGameRuleValue(GameRules.ITEM_DESPAWN_DELAY); + this.lifetime = world.getGameRuleValue(GameRules.ITEM_DESPAWN_DELAY) * 20; if(itemstack == null) { System.err.println("Created EntityItem with no item!"); Thread.dumpStack(); @@ -232,7 +232,7 @@ public class EntityItem extends Entity if(tag.containsKey("Item")) { this.item = ItemStack.readItemStackFromNbt(tag.getCompound("Item")); } - this.lifetime = tag.getIntegerOrDefault("Lifetime", this.world.getGameRuleValue(GameRules.ITEM_DESPAWN_DELAY)); + this.lifetime = tag.getIntegerOrDefault("Lifetime", this.world.getGameRuleValue(GameRules.ITEM_DESPAWN_DELAY) * 20); } @Override diff --git a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java index 1733c2818..10501b833 100644 --- a/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java +++ b/game/core/src/main/java/net/minecraft/core/entity/EntityLightning.java @@ -3,6 +3,7 @@ package net.minecraft.core.entity; import net.minecraft.core.entity.animal.MobWolf; import net.minecraft.core.enums.Difficulty; import net.minecraft.core.block.Blocks; +import net.minecraft.core.data.gamerule.GameRules; import net.minecraft.core.sound.SoundCategory; import net.minecraft.core.util.helper.MathHelper; import com.mojang.nbt.tags.CompoundTag; @@ -61,7 +62,7 @@ public class EntityLightning extends Entity { this.flashes--; this.life = 1; this.seed = this.random.nextLong(); - if (!this.silent && this.world.areBlocksLoaded(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z), 10)) { + if (!this.silent && this.world.getGameRuleValue(GameRules.DO_LIGHTNING_BURN) && this.world.areBlocksLoaded(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z), 10)) { int i = MathHelper.floor(this.x); int j = MathHelper.floor(this.y); int k = MathHelper.floor(this.z); @@ -89,7 +90,7 @@ public class EntityLightning extends Entity { @Override public void spawnInit() { - if (this.world.getDifficulty().id() >= Difficulty.NORMAL.id() && this.world.areBlocksLoaded(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z), 10)) { + if (this.world.getGameRuleValue(GameRules.DO_LIGHTNING_BURN) && this.world.getDifficulty().id() >= Difficulty.NORMAL.id() && this.world.areBlocksLoaded(MathHelper.floor(this.x), MathHelper.floor(this.y), MathHelper.floor(this.z), 10)) { int i = MathHelper.floor(this.x); int k = MathHelper.floor(this.y); int i1 = MathHelper.floor(this.z); diff --git a/game/core/src/main/java/net/minecraft/core/entity/Mob.java b/game/core/src/main/java/net/minecraft/core/entity/Mob.java index 76df3b522..725fdf11f 100644 --- a/game/core/src/main/java/net/minecraft/core/entity/Mob.java +++ b/game/core/src/main/java/net/minecraft/core/entity/Mob.java @@ -484,7 +484,7 @@ public abstract class Mob extends Entity { ItemFood foodItem = (ItemFood) stack.getItem(); - if (foodItem.getTicksPerHeal(stack) == 0 || this.world.getGameRuleValue(GameRules.INSTANT_HEALING)) { + if (foodItem.getTicksPerHeal(stack) == 0 || this.world.getGameRuleValue(GameRules.DO_INSTANT_HEALING)) { heal(foodItem.getHealAmount(stack)); } else { String key = stack.getItemKey(); diff --git a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java index dfa5d25d7..be0aa4c9a 100644 --- a/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java +++ b/game/core/src/main/java/net/minecraft/core/entity/animal/MobPig.java @@ -438,6 +438,7 @@ public class MobPig ItemStack heldItem = player.getHeldItem(); if (heldItem != null && (heldItem.itemID == Blocks.MUSHROOM_BROWN.id() || heldItem.itemID == Blocks.MUSHROOM_RED.id()) && getHealth() < getMaxHealth() && heldItem.consumeItem(player)) { + if (heldItem.stackSize <= 0) player.setHeldItem(null); heal(4); this.world.playSoundAtEntity(player, this, "random.bite", @@ -482,6 +483,7 @@ public class MobPig { if(getSaddled()){ dropItem(Items.SADDLE.id, 1); + setSaddled(false); } super.dropDeathItems(); } 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 63e154732..630ef0df8 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 @@ -121,6 +121,7 @@ public abstract class Player public record FluidPlacement(int dimensionId, int x, int y, int z, long tick) {} public @Nullable FluidPlacement lastAcidPlacement; public @Nullable FluidPlacement lastWaterPlacement; + public static final int PORTAL_DELAY_TICKS = 10; // Must leave a portal for 0.5 seconds before it can attempt to transfer you again public int timeUntilPortal; protected boolean inPortal; public int portalID; @@ -149,13 +150,14 @@ public abstract class Player this.score = 0; this.isSwinging = false; this.swingProgressInt = 0; - this.timeUntilPortal = 20; + this.timeUntilPortal = PORTAL_DELAY_TICKS; this.inPortal = false; this.bobberEntity = null; this.inventoryMenu = new MenuInventory(this.inventory); this.containerMenu = this.inventoryMenu; TilePos spawnPoint = world.getSpawnPoint(); moveTo((double) spawnPoint.x + 0.5D, spawnPoint.y + 1, (double) spawnPoint.z + 0.5D, 0.0F, 0.0F); + setupScale(); // rotOffs = 180F; this.fireImmuneTicks = 20; setTextureIdentifier("minecraft", "char"); @@ -176,7 +178,7 @@ public abstract class Player this.entityData.set(DATA_SELECTED_ART, (byte) ArtType.values.indexOf(selectedArt)); } - private void setupScale() { + protected void setupScale() { this.isDwarf = this.world.getGameRuleValue(GameRules.DWARF_MODE); if (this.isDwarf) { setSize(0.6f, isSneaking() ? 0.5f : 0.8f); @@ -854,7 +856,7 @@ public abstract class Player final @NotNull EntityItem itemEntity = new EntityItem(this.world, this.x, (this.y - 0.3) + (double) this.getHeadHeight(), this.z, stack); itemEntity.pickupDelay = 40; - itemEntity.lifetime = this.world.getGameRuleValue(GameRules.DROPPED_ITEM_DESPAWN_DELAY); + itemEntity.lifetime = this.world.getGameRuleValue(GameRules.PLAYER_ITEM_DESPAWN_DELAY) * 20; if (randomDirection) { final float speed = this.random.nextFloat() * 0.5F; @@ -1638,7 +1640,7 @@ public abstract class Player @Override public void handlePortal(int portalBlockId, DyeColor portalColor) { if (this.timeUntilPortal > 0) { - this.timeUntilPortal = 10; + this.timeUntilPortal = PORTAL_DELAY_TICKS; } else { this.portalID = portalBlockId; this.portalColor = portalColor; diff --git a/game/core/src/main/java/net/minecraft/core/enums/EnumFireSpread.java b/game/core/src/main/java/net/minecraft/core/enums/EnumFireSpread.java new file mode 100644 index 000000000..060f52dfc --- /dev/null +++ b/game/core/src/main/java/net/minecraft/core/enums/EnumFireSpread.java @@ -0,0 +1,7 @@ +package net.minecraft.core.enums; + +public enum EnumFireSpread { + ALL, + FOLIAGE, + NONE +} diff --git a/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeGameruleGeneric.java b/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeGameruleGeneric.java index 337a2cf72..170523141 100644 --- a/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeGameruleGeneric.java +++ b/game/core/src/main/java/net/minecraft/core/net/command/arguments/ArgumentTypeGameruleGeneric.java @@ -8,8 +8,10 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.core.data.gamerule.GameRule; +import net.minecraft.core.data.gamerule.GameRuleEnum; import net.minecraft.core.lang.I18n; +import java.util.Locale; import java.util.concurrent.CompletableFuture; public class ArgumentTypeGameruleGeneric implements ArgumentType { @@ -39,6 +41,15 @@ public class ArgumentTypeGameruleGeneric implements ArgumentType { @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + if (this.gameRule instanceof GameRuleEnum enumRule) { + for (final Enum value : enumRule.getValues()) { + final String name = value.name().toLowerCase(Locale.ROOT); + if (name.startsWith(builder.getRemainingLowerCase())) { + builder.suggest(name); + } + } + return builder.buildFuture(); + } return ArgumentType.super.listSuggestions(context, builder); } } diff --git a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandGameRule.java b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandGameRule.java index 00b1d2c54..2d35a1cba 100644 --- a/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandGameRule.java +++ b/game/core/src/main/java/net/minecraft/core/net/command/commands/CommandGameRule.java @@ -18,19 +18,20 @@ public class CommandGameRule implements CommandManager.CommandRegistry { public void register(CommandDispatcher dispatcher) { final ArgumentBuilderLiteral argumentBuilder = ArgumentBuilderLiteral.literal("gamerule").requires(CommandSource::hasAdmin); for (final GameRule gameRule : Registries.GAME_RULES) { + final String argName = gameRule.getValueArgumentName(); ArgumentBuilderRequired gameRuleValueArgument; if (gameRule instanceof GameRuleBoolean) { - gameRuleValueArgument = ArgumentBuilderRequired.argument("value", ArgumentTypeBool.bool()) + gameRuleValueArgument = ArgumentBuilderRequired.argument(argName, ArgumentTypeBool.bool()) .executes(c -> { - c.getSource().getWorld().getLevelData().getGameRules().setValue((GameRuleBoolean) gameRule, ArgumentTypeBool.getBool(c, "value")); + c.getSource().getWorld().getLevelData().getGameRules().setValue((GameRuleBoolean) gameRule, ArgumentTypeBool.getBool(c, argName)); c.getSource().sendPacketToAllPlayers(() -> new PacketGameRule(c.getSource().getWorld().getLevelData().getGameRules())); - c.getSource().sendTranslatableMessage("command.commands.gamerule.set", gameRule.getKey(), ArgumentTypeBool.getBool(c, "value")); + c.getSource().sendTranslatableMessage("command.commands.gamerule.set", gameRule.getKey(), ArgumentTypeBool.getBool(c, argName)); return Command.SINGLE_SUCCESS; }); } else { - gameRuleValueArgument = ArgumentBuilderRequired.argument("value", ArgumentTypeGameruleGeneric.gameRule(gameRule)) + gameRuleValueArgument = ArgumentBuilderRequired.argument(argName, ArgumentTypeGameruleGeneric.gameRule(gameRule)) .executes(c -> { - Object o = c.getArgument("value", Object.class); + Object o = c.getArgument(argName, Object.class); c.getSource().getWorld().getLevelData().getGameRules().setValue((GameRule) gameRule, o); c.getSource().sendPacketToAllPlayers(() -> new PacketGameRule(c.getSource().getWorld().getLevelData().getGameRules())); c.getSource().sendTranslatableMessage("command.commands.gamerule.set", gameRule.getKey(), o); diff --git a/game/core/src/main/java/net/minecraft/core/world/Explosion.java b/game/core/src/main/java/net/minecraft/core/world/Explosion.java index ed6faa107..7c94fdc0a 100644 --- a/game/core/src/main/java/net/minecraft/core/world/Explosion.java +++ b/game/core/src/main/java/net/minecraft/core/world/Explosion.java @@ -45,9 +45,13 @@ public class Explosion { this.explosionY = y; this.explosionZ = z; this.destroyBlocks = true; - if (!world.getGameRuleValue(GameRules.MOB_GRIEFING)) { + if (!world.getGameRuleValue(GameRules.DO_MOB_GRIEFING)) { this.destroyBlocks = exploder == null || exploder instanceof Player; } + + if (!world.isClientSide && exploder == null && !world.getGameRuleValue(GameRules.DO_EXPLOSION_GRIEFING)) { + this.destroyBlocks = false; + } } public void explode() { 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 5f4aa2f35..b6a74bc6c 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 @@ -1377,8 +1377,8 @@ public abstract class World implements MutableWorldSource { public void removePlayer(final Entity entity) { entity.remove(); - if (entity instanceof Player) { - this.players.remove((Player) entity); + if (entity instanceof Player player) { + this.players.remove(player); this.updateEnoughPlayersSleepingFlag(null); } final int i = entity.chunkCoordX; diff --git a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java index d5b3e4ec5..c720a92c2 100644 --- a/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java +++ b/game/core/src/main/java/net/minecraft/core/world/chunk/ChunkSection.java @@ -1,5 +1,6 @@ package net.minecraft.core.world.chunk; +import net.minecraft.core.block.Block; import net.minecraft.core.block.Blocks; import net.minecraft.core.data.registry.Registries; import net.minecraft.core.entity.Entity; @@ -11,6 +12,7 @@ import net.minecraft.core.world.biome.Biome; import net.minecraft.core.world.data.ChunkUnsignedByteArray; import net.minecraft.core.world.pos.ChunkSectionTilePos; import net.minecraft.core.world.pos.ChunkSectionTilePosc; +import net.minecraft.core.world.pos.TilePos; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.primitives.AABBd; @@ -65,6 +67,10 @@ public class ChunkSection { return ChunkSection.makeBiomeIndex(new ChunkSectionTilePos(x, y, z)); } + public boolean isEmpty() { + return this.blocks == null; + } + public int getBlockId(final @NotNull ChunkSectionTilePosc sectionPos) { if (!sectionPos.inBounds() || this.blocks == null) { return 0; @@ -267,8 +273,30 @@ public class ChunkSection { } } - public void onLoad(World world) { + public void onLoad(@NotNull World world) { world.addLoadedEntities(this.entities); + + if (this.isEmpty() || world.isClientSide || world.scheduledUpdatesAreImmediate) { + return; + } + + final int blockX = this.chunk.pos.x * Chunk.CHUNK_SIZE_X; + final int blockZ = this.chunk.pos.z * Chunk.CHUNK_SIZE_Z; + final int sectionBlockY = this.yPosition * SECTION_SIZE_Y; + final ChunkSectionTilePos sectionPos = new ChunkSectionTilePos(); + final TilePos tilePos = new TilePos(); + for (int y = 0; y < SECTION_SIZE_Y; y++) { + for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) { + for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) { + final int id = this.getBlockId(sectionPos.set(x, y, z)); + if (id == 0) { + continue; + } + final Block block = Blocks.getBlock(id); + block.onChunkLoad(world, tilePos.set(blockX + x, sectionBlockY + y, blockZ + z)); + } + } + } } public void onUnload(World world) { diff --git a/game/core/src/main/resources/assets/minecraft/lang/en_US/gamerules.lang b/game/core/src/main/resources/assets/minecraft/lang/en_US/gamerules.lang index 48e921839..c3e4cf41a 100644 --- a/game/core/src/main/resources/assets/minecraft/lang/en_US/gamerules.lang +++ b/game/core/src/main/resources/assets/minecraft/lang/en_US/gamerules.lang @@ -12,21 +12,28 @@ gamerule.treecapitator.name=Treecapitator gamerule.treecapitator.desc=If enabled, trees will be instantly mined in their entirety when their bottom log is broken with an axe. gamerule.dwarf_mode.name=Dwarf Mode gamerule.dwarf_mode.desc=If enabled, all players will become one-block-tall dwarves. -gamerule.mob_griefing.name=Mob Griefing -gamerule.mob_griefing.desc=If disabled, explosions created by mobs will not destroy blocks. +gamerule.do_mob_griefing.name=Mob Griefing +gamerule.do_mob_griefing.desc=If disabled, explosions created by mobs will not destroy blocks. +gamerule.do_explosion_griefing.name=Explosion Griefing +gamerule.do_explosion_griefing.desc=If disabled, explosions without a source entity, such as TNT and embers, will not destroy blocks or start fires. gamerule.do_day_night_cycle.name=Day/Night Cycle gamerule.do_day_night_cycle.desc=If disabled, the day/night cycle is paused. gamerule.do_weather_cycle.name=Weather gamerule.do_weather_cycle.desc=If disabled, the weather will not randomly change. -gamerule.do_fire_spread.name=Fire Spread -gamerule.do_fire_spread.desc=If disabled, fire will not spread. -gamerule.instant_healing.name=Instant Healing from Food -gamerule.instant_healing.desc=If enabled, food will heal the player instantly as it did in older versions of BTA!. -gamerule.acid_melt_rate.name=Acid Melt Rate -gamerule.acid_melt_rate.desc=Ticks between each acid bank tick, durability melt, and post-exit drain pulse. Default matches fire damage (every 20 ticks). Lower values run faster. +gamerule.fire_spread.name=Fire Spread +gamerule.fire_spread.desc=Controls what fire can spread to. All - all blocks can be spread to; Foliage - only logs, leaves, and moss; None - no blocks can be spread to +gamerule.fire_spread.value.all=All +gamerule.fire_spread.value.foliage=Foliage +gamerule.fire_spread.value.none=None +gamerule.do_fire_burn.name=Fire Consumes Blocks +gamerule.do_fire_burn.desc=If disabled, fire will not consume blocks. +gamerule.do_lightning_burn.name=Lightning Starts Fires +gamerule.do_lightning_burn.desc=If disabled, lightning strikes will not start fires. +gamerule.do_instant_healing.name=Instant Healing from Food +gamerule.do_instant_healing.desc=If enabled, food will heal the player instantly as it did in older versions of BTA!. gamerule.random_tick_speed.name=Random Tick Rate gamerule.random_tick_speed.desc=Determines how many blocks are randomly ticked per game tick. -gamerule.dropped_item_despawn_delay.name=Dropped Item Despawn Delay -gamerule.dropped_item_despawn_delay.desc=The number of ticks until an item dropped by a player despawns. gamerule.item_despawn_delay.name=Item Despawn Delay -gamerule.item_despawn_delay.desc=The number of ticks until an item that was not dropped by a player despawns. +gamerule.item_despawn_delay.desc=The number of seconds until an item despawns. +gamerule.player_item_despawn_delay.name=Player Item Despawn Delay +gamerule.player_item_despawn_delay.desc=The number of seconds until an item dropped by a player (manually or on death) despawns. 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 130067434..bb0bb3cc3 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 @@ -184,6 +184,7 @@ public class PlayerServer extends Player implements ContainerListener { @Override public void tick() { + setupScale(); playerController.tick(); ticksOfInvuln--; containerMenu.broadcastChanges(); @@ -293,56 +294,6 @@ public class PlayerServer extends Player implements ContainerListener { } } - if (inPortal && !hasNoPhysics()) - { - Dimension targetDim = ((BlockLogicPortal) Blocks.blocksList[portalID].getLogic()).targetDimension; - boolean netherAllowed = mcServer.propertyManager.getBooleanProperty("allow-nether", true); - boolean driftAllowed = mcServer.propertyManager.getBooleanProperty("allow-drift", false); - if ((netherAllowed && targetDim == Dimension.NETHER) || (driftAllowed && targetDim == Dimension.DRIFT) || (targetDim != Dimension.NETHER && targetDim != Dimension.DRIFT)) - { - if (containerMenu != inventoryMenu) - { - usePersonalCraftingInventory(); - } - if (vehicle != null && !(vehicle instanceof MobPig)) - { - startRiding(vehicle); - } - else - { - timeInPortal += 0.0125F; - if (timeInPortal >= 1.0F || getGamemode().hasInstantPortalTravel()) - { - timeInPortal = 1.0F; - timeUntilPortal = 10; - if (dimension == targetDim.id) - { - mcServer.playerList.sendPlayerToOtherDimension(this, 0, portalColor, true); - } - else - { - mcServer.playerList.sendPlayerToOtherDimension(this, targetDim.id, portalColor, true); - } - } - } - inPortal = false; - } - } - else - { - if (timeInPortal > 0.0F) - { - timeInPortal -= 0.05F; - } - if (timeInPortal < 0.0F) - { - timeInPortal = 0.0F; - } - } - if (timeUntilPortal > 0) - { - timeUntilPortal--; - } if (getHealth() != lastHealth) { playerNetServerHandler.sendPacket(new PacketSetHealth(getHealth())); @@ -396,6 +347,45 @@ public class PlayerServer extends Player implements ContainerListener { @Override public void onLivingUpdate() { + if (inPortal && !hasNoPhysics()) { + inPortal = false; + Dimension targetDim = ((BlockLogicPortal) Blocks.blocksList[portalID].getLogic()).targetDimension; + boolean netherAllowed = mcServer.propertyManager.getBooleanProperty("allow-nether", true); + boolean driftAllowed = mcServer.propertyManager.getBooleanProperty("allow-drift", false); + if ((netherAllowed && targetDim == Dimension.NETHER) || (driftAllowed && targetDim == Dimension.DRIFT) || (targetDim != Dimension.NETHER && targetDim != Dimension.DRIFT)) { + if (containerMenu != inventoryMenu) { + usePersonalCraftingInventory(); + } + if (vehicle != null && !(vehicle instanceof MobPig)) { + startRiding(vehicle); + } + else { + timeInPortal += 0.0125F; + if (timeInPortal >= 1.0F || (getGamemode().hasInstantPortalTravel())) { + timeInPortal = 1.0F; + timeUntilPortal = PORTAL_DELAY_TICKS; + if (dimension == targetDim.id) { + mcServer.playerList.sendPlayerToOtherDimension(this, 0, portalColor, true); + } + else { + mcServer.playerList.sendPlayerToOtherDimension(this, targetDim.id, portalColor, true); + } + } + } + } + } + else { + if (timeInPortal > 0.0F) { + timeInPortal -= 0.05F; + } + if (timeInPortal < 0.0F) { + timeInPortal = 0.0F; + } + } + if (timeUntilPortal > 0) { + timeUntilPortal--; + } + super.onLivingUpdate(); if (tickCount % 10 == 0){ Item arrow = getNextArrow(); diff --git a/game/server/src/main/java/net/minecraft/server/net/PlayerList.java b/game/server/src/main/java/net/minecraft/server/net/PlayerList.java index 5c0b843da..acfda0aac 100644 --- a/game/server/src/main/java/net/minecraft/server/net/PlayerList.java +++ b/game/server/src/main/java/net/minecraft/server/net/PlayerList.java @@ -279,18 +279,18 @@ public class PlayerList public void sendPlayerToOtherDimension(PlayerServer playerServer, int targetDim, DyeColor portalColor, boolean generatePortal) { - WorldServer worldserver = server.getDimensionWorld(playerServer.dimension); + WorldServer currentDimensionWorld = server.getDimensionWorld(playerServer.dimension); Dimension lastDim = Dimension.getDimensionList().get(playerServer.dimension); Dimension newDim = Dimension.getDimensionList().get(targetDim); Entity mount = playerServer.vehicle instanceof MobPig ? (Entity) playerServer.vehicle : null; playerServer.dimension = targetDim; - WorldServer worldserver1 = server.getDimensionWorld(playerServer.dimension); - playerServer.playerNetServerHandler.sendPacket(new PacketRespawn((byte) playerServer.dimension, (byte) Registries.WORLD_TYPES.getNumericIdOfItem(worldserver1.getWorldType()))); - worldserver.removePlayer(playerServer); + WorldServer targetDimensionWorld = server.getDimensionWorld(playerServer.dimension); + playerServer.playerNetServerHandler.sendPacket(new PacketRespawn((byte) playerServer.dimension, (byte) Registries.WORLD_TYPES.getNumericIdOfItem(targetDimensionWorld.getWorldType()))); + currentDimensionWorld.removePlayer(playerServer); if (mount != null) { - worldserver.removePlayer(mount); + currentDimensionWorld.removePlayer(mount); } playerServer.removed = false; double x = playerServer.x; @@ -313,25 +313,25 @@ public class PlayerList playerServer.dimensionEnterCoordinate = newCoordinates; if (playerServer.isAlive()) { - worldserver.updateEntityWithOptionalForce(playerServer, false); + currentDimensionWorld.updateEntityWithOptionalForce(playerServer, false); } if (playerServer.isAlive()) { - worldserver1.entityJoinedWorld(playerServer); + targetDimensionWorld.entityJoinedWorld(playerServer); playerServer.teleport(x, playerServer.y, z, playerServer.yRot, playerServer.xRot); - worldserver1.updateEntityWithOptionalForce(playerServer, false); + targetDimensionWorld.updateEntityWithOptionalForce(playerServer, false); if (generatePortal){ - worldserver1.getChunkProvider().chunkLoadOverride = true; - (new PortalHandler()).teleportEntity(worldserver1, playerServer, portalColor, lastDim, newDim); - worldserver1.getChunkProvider().chunkLoadOverride = false; + targetDimensionWorld.getChunkProvider().chunkLoadOverride = true; + (new PortalHandler()).teleportEntity(targetDimensionWorld, playerServer, portalColor, lastDim, newDim); + targetDimensionWorld.getChunkProvider().chunkLoadOverride = false; } } syncPlayerDimension(playerServer); playerServer.playerNetServerHandler.teleportAndRotate(playerServer.x, playerServer.y, playerServer.z, playerServer.yRot, playerServer.xRot); server.playerList.sendPacketToAllPlayers(new PacketPlayerGamemode(playerServer.id, playerServer.gamemode.getId())); - playerServer.setWorld(worldserver1); - setTime(playerServer, worldserver1); + playerServer.setWorld(targetDimensionWorld); + setTime(playerServer, targetDimensionWorld); initializePlayerObject(playerServer); playerServer.playerNetServerHandler.sendPacket(new PacketGameRule(server.getDimensionWorld(0).getLevelData().getGameRules())); playerServer.playerNetServerHandler.sendPacket(new PacketSetHotbarOffset(playerServer.inventory.getHotbarOffset())); @@ -339,9 +339,9 @@ public class PlayerList if (mount != null && playerServer.isAlive()) { mount.removed = false; - mount.world = worldserver1; + mount.world = targetDimensionWorld; mount.moveTo(playerServer.x, playerServer.y, playerServer.z, playerServer.yRot, mount.xRot); - worldserver1.entityJoinedWorld(mount); + targetDimensionWorld.entityJoinedWorld(mount); playerServer.playerNetServerHandler.sendPacket(new PacketSetRiding(playerServer, mount)); } } 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 ae6bce942..72f6faebd 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 @@ -160,8 +160,8 @@ public class PacketHandlerServer extends PacketHandler } // In a entity vehicle - if (this.playerEntity.vehicle instanceof Entity) { - this.playerEntity.vehicle.positionRider(); + if (this.playerEntity.vehicle instanceof Entity vehicle) { + vehicle.positionRider(); double xd = 0.0D; double zd = 0.0D; if (packetMovePlayer.hasPosition && packetMovePlayer.y == -999D) { @@ -176,8 +176,8 @@ public class PacketHandlerServer extends PacketHandler this.playerEntity.zd = zd; // TODO: Is this needing? It does allow for fast-tick exploits. // Update: Removing it breaks boats, so keep it for now - worldserver.updateEntityWithOptionalForce(((Entity) this.playerEntity.vehicle), false); - this.playerEntity.vehicle.positionRider(); + worldserver.updateEntityWithOptionalForce(vehicle, false); + vehicle.positionRider(); this.mcServer.playerList.onPlayerMoved(this.playerEntity); return; } @@ -330,7 +330,8 @@ public class PacketHandlerServer extends PacketHandler double playerDistY = this.playerEntity.y - (y + 0.5); double playerDistZ = this.playerEntity.z - (z + 0.5); double playerDist = playerDistX * playerDistX + playerDistY * playerDistY + playerDistZ * playerDistZ; - if (playerDist > 44.0) { + double maxDist = this.playerEntity.getGamemode().getBlockReachDistance() + 2.5; + if (playerDist > maxDist * maxDist) { return; } @@ -373,6 +374,8 @@ public class PacketHandlerServer extends PacketHandler WorldServer worldserver = this.mcServer.getDimensionWorld(this.playerEntity.dimension); ItemStack itemstack = this.playerEntity.inventory.getCurrentItem(); boolean ignoreSpawnProtection = this.mcServer.spawnProtectionRange <= 0 || worldserver.dimension.id != 0 || this.mcServer.playerList.isOp(this.playerEntity.uuid); + double maxPlaceDist = this.playerEntity.getGamemode().getBlockReachDistance() + 3.5; + double maxPlaceDistSq = maxPlaceDist * maxPlaceDist; switch (packet.type) { case PacketUseOrPlaceItemStack.TYPE_USE_OR_PLACE_ON_TILE: { int x = packet.xPosition; @@ -387,7 +390,7 @@ public class PacketHandlerServer extends PacketHandler if (i1 > j1) { j1 = i1; } - if (this.hasMoved && this.playerEntity.distanceToSqr((double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D) < 64D && (j1 > this.mcServer.spawnProtectionRange || ignoreSpawnProtection)) { + if (this.hasMoved && this.playerEntity.distanceToSqr((double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D) < maxPlaceDistSq && (j1 > this.mcServer.spawnProtectionRange || ignoreSpawnProtection)) { this.playerEntity.playerController.useOrPlaceItemStackOnTile(this.playerEntity, worldserver, itemstack, x, y, z, direction.side(), xPlaced, yPlaced); } this.playerEntity.playerNetServerHandler.sendPacket(new PacketBlockUpdate(x, y, z, worldserver)); @@ -417,7 +420,7 @@ public class PacketHandlerServer extends PacketHandler if (i1 > j1) { j1 = i1; } - if (this.hasMoved && this.playerEntity.distanceToSqr((double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D) < 64D && (j1 > this.mcServer.spawnProtectionRange || ignoreSpawnProtection)) { + if (this.hasMoved && this.playerEntity.distanceToSqr((double) x + 0.5D, (double) y + 0.5D, (double) z + 0.5D) < maxPlaceDistSq && (j1 > this.mcServer.spawnProtectionRange || ignoreSpawnProtection)) { this.playerEntity.playerController.placeItemStackOnTile(this.playerEntity, worldserver, itemstack, x, y, z, direction.side(), xPlaced, yPlaced); } this.playerEntity.playerNetServerHandler.sendPacket(new PacketBlockUpdate(x, y, z, worldserver)); @@ -619,7 +622,8 @@ public class PacketHandlerServer extends PacketHandler // real problem is probably entity ids being synced incorrectly, but I have no idea what to do with that if(targetEntity == null) return; - if (this.playerEntity.distanceToSqr(targetEntity) < 36D) { + double maxEntityDist = this.playerEntity.getGamemode().getEntityReachDistance() + 3.0; + if (this.playerEntity.distanceToSqr(targetEntity) < maxEntityDist * maxEntityDist) { boolean canAttack = this.playerEntity.canEntityBeSeen(targetEntity); if (!canAttack) {