From 2b0745dc2c2cd87e2b2db7a0602aec6f87de9903 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Wed, 22 Apr 2020 23:25:57 +0200 Subject: [PATCH] 20w17a --- .../api/rewriters/EntityRewriterBase.java | 65 ++++++++++++++-- .../packets/EntityPackets1_13.java | 2 +- .../packets/EntityPackets1_14.java | 2 +- .../packets/EntityPackets1_15.java | 2 +- .../Protocol1_15_2To1_16.java | 49 ++++++++---- .../packets/BlockItemPackets1_16.java | 15 +++- .../packets/EntityPackets1_16.java | 18 ++--- .../viabackwards/data/mapping-1.15to1.16.json | 29 +++++-- .../data/translation-mappings.json | 76 +++++++++++++++++-- 9 files changed, 207 insertions(+), 51 deletions(-) diff --git a/core/src/main/java/nl/matsv/viabackwards/api/rewriters/EntityRewriterBase.java b/core/src/main/java/nl/matsv/viabackwards/api/rewriters/EntityRewriterBase.java index 06f22088..519767b3 100644 --- a/core/src/main/java/nl/matsv/viabackwards/api/rewriters/EntityRewriterBase.java +++ b/core/src/main/java/nl/matsv/viabackwards/api/rewriters/EntityRewriterBase.java @@ -29,17 +29,24 @@ import java.util.List; import java.util.Map; import java.util.logging.Logger; +/** + * Entity rewriter base class. + * + * @see EntityRewriter + * @see LegacyEntityRewriter + */ public abstract class EntityRewriterBase extends Rewriter { private final Map entityTypes = new HashMap<>(); private final List metaHandlers = new ArrayList<>(); private final MetaType displayNameMetaType; private final int displayNameIndex; + private Map typeMapping; - protected EntityRewriterBase(T protocol) { + EntityRewriterBase(T protocol) { this(protocol, MetaType1_9.String, 2); } - protected EntityRewriterBase(T protocol, MetaType displayNameMetaType, int displayNameIndex) { + EntityRewriterBase(T protocol, MetaType displayNameMetaType, int displayNameIndex) { super(protocol); this.displayNameMetaType = displayNameMetaType; this.displayNameIndex = displayNameIndex; @@ -61,15 +68,63 @@ public abstract class EntityRewriterBase extends Re return entityTypes.get(type); } + /** + * @param oldType old type of the higher version + * @param replacement new type of the higher version + * @return created entity data + * @see #mapEntityDirect(EntityType, EntityType) for id only rewriting + */ protected EntityData mapEntity(EntityType oldType, EntityType replacement) { Preconditions.checkArgument(oldType.getClass() == replacement.getClass()); // Already rewrite the id here - EntityData data = new EntityData(oldType.getId(), getOldEntityId(replacement.getId())); + int mappedReplacementId = getOldEntityId(replacement.getId()); + EntityData data = new EntityData(oldType.getId(), mappedReplacementId); + mapEntityDirect(oldType.getId(), mappedReplacementId); entityTypes.put(oldType, data); return data; } + /** + * Maps entity ids based on the enum constant's names. + * + * @param oldTypes entity types of the higher version + * @param newTypeClass entity types enum class of the lower version + * @param new type class + */ + public & EntityType> void mapTypes(EntityType[] oldTypes, Class newTypeClass) { + if (typeMapping == null) typeMapping = new HashMap<>(oldTypes.length); + for (EntityType oldType : oldTypes) { + try { + T newType = Enum.valueOf(newTypeClass, oldType.name()); + typeMapping.put(oldType.getId(), newType.getId()); + } catch (IllegalArgumentException e) { + // Missing ones should be mapped BEFORE using this method + if (!typeMapping.containsKey(oldType.getId())) { + ViaBackwards.getPlatform().getLogger().warning("Could not find new entity type for " + oldType + "! " + + "Old type: " + oldType.getClass().getSimpleName() + " New type: " + newTypeClass.getSimpleName()); + } + } + } + } + + /** + * Directly maps the entity without any other rewriting. + * + * @param oldType type of the higher version + * @param newType type of the lower version + * @see #mapEntity(EntityType, EntityType) for mapping with data + */ + public void mapEntityDirect(EntityType oldType, EntityType newType) { + Preconditions.checkArgument(oldType.getClass() != newType.getClass()); + mapEntityDirect(oldType.getId(), newType.getId()); + } + + private void mapEntityDirect(int oldType, int newType) { + if (typeMapping == null) typeMapping = new HashMap<>(); + typeMapping.put(oldType, newType); + } + public MetaHandlerSettings registerMetaHandler() { MetaHandlerSettings settings = new MetaHandlerSettings(); metaHandlers.add(settings); @@ -241,7 +296,7 @@ public abstract class EntityRewriterBase extends Re protected abstract EntityType getTypeFromId(int typeId); - protected int getOldEntityId(int newId) { - return newId; + public int getOldEntityId(int newId) { + return typeMapping != null ? typeMapping.getOrDefault(newId, newId) : newId; } } diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_12_2to1_13/packets/EntityPackets1_13.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_12_2to1_13/packets/EntityPackets1_13.java index f58ff691..0609f630 100644 --- a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_12_2to1_13/packets/EntityPackets1_13.java +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_12_2to1_13/packets/EntityPackets1_13.java @@ -430,7 +430,7 @@ public class EntityPackets1_13 extends LegacyEntityRewriter { } @Override - protected int getOldEntityId(final int newId) { + public int getOldEntityId(final int newId) { return EntityTypeMapping.getOldEntityId(newId); } } diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/Protocol1_15_2To1_16.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/Protocol1_15_2To1_16.java index f3c27cfe..68a4924a 100644 --- a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/Protocol1_15_2To1_16.java +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/Protocol1_15_2To1_16.java @@ -8,7 +8,6 @@ import nl.matsv.viabackwards.api.rewriters.TranslatableRewriter; import nl.matsv.viabackwards.protocol.protocol1_15_2to1_16.data.BackwardsMappings; import nl.matsv.viabackwards.protocol.protocol1_15_2to1_16.packets.BlockItemPackets1_16; import nl.matsv.viabackwards.protocol.protocol1_15_2to1_16.packets.EntityPackets1_16; -import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.remapper.PacketRemapper; import us.myles.ViaVersion.api.rewriters.TagRewriter; @@ -17,6 +16,10 @@ import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_16to1_15_2.Protocol1_16To1_15_2; import us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data.MappingData; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; +import us.myles.ViaVersion.util.GsonUtil; +import us.myles.viaversion.libs.gson.JsonElement; +import us.myles.viaversion.libs.gson.JsonObject; +import us.myles.viaversion.libs.gson.JsonPrimitive; import java.util.UUID; @@ -29,9 +32,35 @@ public class Protocol1_15_2To1_16 extends BackwardsProtocol { executeAsyncAfterLoaded(Protocol1_16To1_15_2.class, BackwardsMappings::init); (blockItemPackets = new BlockItemPackets1_16(this)).register(); - new EntityPackets1_16(this).register(); + EntityPackets1_16 entityPackets = new EntityPackets1_16(this); + entityPackets.register(); - TranslatableRewriter translatableRewriter = new TranslatableRewriter(this); + TranslatableRewriter translatableRewriter = new TranslatableRewriter(this) { + @Override + public String processTranslate(String value) { + JsonObject object = GsonUtil.getGson().fromJson(value, JsonObject.class); + JsonElement with = object.get("with"); + if (with == null) { + return super.processTranslate(value); + } + + for (JsonElement element : with.getAsJsonArray()) { + if (!element.isJsonObject()) continue; + + JsonElement hoverEventElement = element.getAsJsonObject().get("hoverEvent"); + if (hoverEventElement == null) continue; + + JsonObject hoverEvent = hoverEventElement.getAsJsonObject(); + JsonElement contentsElement = hoverEvent.remove("contents"); + if (contentsElement != null) { + JsonObject values = new JsonObject(); + values.add("text", new JsonPrimitive(contentsElement.toString())); + hoverEvent.add("value", values); + } + } + return super.processTranslate(object.toString()); + } + }; translatableRewriter.registerBossBar(0x0D, 0x0D); translatableRewriter.registerChatMessage(0x0F, 0x0F); translatableRewriter.registerCombatEvent(0x33, 0x33); @@ -100,7 +129,7 @@ public class Protocol1_15_2To1_16 extends BackwardsProtocol { new TagRewriter(this, id -> BackwardsMappings.blockMappings.getNewId(id), id -> { Integer oldId = MappingData.oldToNewItems.inverse().get(id); return oldId != null ? oldId : -1; - }, Protocol1_15_2To1_16::getNewEntityId).register(0x5C, 0x5C); + }, entityPackets::getOldEntityId).register(0x5C, 0x5C); registerOutgoing(State.PLAY, 0x43, 0x4E); registerOutgoing(State.PLAY, 0x44, 0x43); @@ -148,17 +177,6 @@ public class Protocol1_15_2To1_16 extends BackwardsProtocol { registerIncoming(State.PLAY, 0x2D, 0x2C); } - public static int getNewEntityId(final int oldId) { - if (oldId == 95) { - return 57; - } else if (oldId > 56 && oldId < 95) { - return oldId + 1; - } else if (oldId > 103) { - return oldId - 1; - } - return oldId; - } - public static int getNewBlockStateId(int id) { int newId = BackwardsMappings.blockStateMappings.getNewId(id); if (newId == -1) { @@ -168,7 +186,6 @@ public class Protocol1_15_2To1_16 extends BackwardsProtocol { return newId; } - public static int getNewBlockId(int id) { int newId = BackwardsMappings.blockMappings.getNewId(id); if (newId == -1) { diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/BlockItemPackets1_16.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/BlockItemPackets1_16.java index bf07e5b0..5c7c056f 100644 --- a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/BlockItemPackets1_16.java +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/BlockItemPackets1_16.java @@ -15,9 +15,12 @@ import us.myles.ViaVersion.api.type.types.UUIDIntArrayType; import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.types.Chunk1_15Type; import us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data.MappingData; +import us.myles.ViaVersion.protocols.protocol1_16to1_15_2.types.Chunk1_16Type; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; +import us.myles.ViaVersion.util.CompactArrayUtil; import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag; import us.myles.viaversion.libs.opennbt.tag.builtin.IntArrayTag; +import us.myles.viaversion.libs.opennbt.tag.builtin.LongArrayTag; import us.myles.viaversion.libs.opennbt.tag.builtin.StringTag; import us.myles.viaversion.libs.opennbt.tag.builtin.Tag; @@ -118,7 +121,9 @@ public class BlockItemPackets1_16 extends nl.matsv.viabackwards.api.rewriters.It public void registerMap() { handler(wrapper -> { ClientWorld clientWorld = wrapper.user().get(ClientWorld.class); - Chunk chunk = wrapper.passthrough(new Chunk1_15Type(clientWorld)); + Chunk chunk = wrapper.read(new Chunk1_16Type(clientWorld)); + wrapper.write(new Chunk1_15Type(clientWorld), chunk); + for (int i = 0; i < chunk.getSections().length; i++) { ChunkSection section = chunk.getSections()[i]; if (section == null) continue; @@ -128,6 +133,14 @@ public class BlockItemPackets1_16 extends nl.matsv.viabackwards.api.rewriters.It } } + CompoundTag heightMaps = chunk.getHeightMap(); + for (Tag heightMapTag : heightMaps) { + LongArrayTag heightMap = (LongArrayTag) heightMapTag; + int[] heightMapData = new int[256]; + CompactArrayUtil.iterateCompactArrayWithPadding(9, heightMapData.length, heightMap.getValue(), (i, v) -> heightMapData[i] = v); + heightMap.setValue(CompactArrayUtil.createCompactArray(9, heightMapData.length, i -> heightMapData[i])); + } + if (chunk.isBiomeData()) { for (int i = 0; i < 1024; i++) { int biome = chunk.getBiomeData()[i]; diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/EntityPackets1_16.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/EntityPackets1_16.java index b4ee3538..9eac8b7d 100644 --- a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/EntityPackets1_16.java +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/packets/EntityPackets1_16.java @@ -96,15 +96,19 @@ public class EntityPackets1_16 extends EntityRewriter { return meta; }); + mapEntityDirect(Entity1_16Types.EntityType.ZOMBIFIED_PIGLIN, Entity1_15Types.EntityType.ZOMBIE_PIGMAN); + mapEntity(Entity1_16Types.EntityType.HOGLIN, Entity1_16Types.EntityType.COW).jsonName("Hoglin"); mapEntity(Entity1_16Types.EntityType.ZOGLIN, Entity1_16Types.EntityType.COW).jsonName("Zoglin"); mapEntity(Entity1_16Types.EntityType.PIGLIN, Entity1_16Types.EntityType.ZOMBIFIED_PIGLIN).jsonName("Piglin"); mapEntity(Entity1_16Types.EntityType.STRIDER, Entity1_16Types.EntityType.MAGMA_CUBE).jsonName("Strider"); + mapTypes(Entity1_16Types.EntityType.values(), Entity1_15Types.EntityType.class); + registerMetaHandler().filter(Entity1_16Types.EntityType.ZOGLIN, 16).removed(); registerMetaHandler().filter(Entity1_16Types.EntityType.HOGLIN, 15).removed(); - registerMetaHandler().filter(Entity1_16Types.EntityType.PIGLIN, 16).removed(); // charging crossbow + registerMetaHandler().filter(Entity1_16Types.EntityType.PIGLIN, 16).removed(); registerMetaHandler().filter(Entity1_16Types.EntityType.PIGLIN, 17).removed(); registerMetaHandler().filter(Entity1_16Types.EntityType.STRIDER, 15).handle(meta -> { @@ -132,16 +136,4 @@ public class EntityPackets1_16 extends EntityRewriter { protected EntityType getTypeFromId(int typeId) { return Entity1_16Types.getTypeFromId(typeId); } - - @Override - protected int getOldEntityId(int newId) { - if (newId == Entity1_16Types.EntityType.HOGLIN.getId() || newId == Entity1_16Types.EntityType.ZOGLIN.getId()) { - return Entity1_15Types.EntityType.COW.getId(); - } else if (newId == Entity1_16Types.EntityType.PIGLIN.getId()) { - return Entity1_15Types.EntityType.ZOMBIE_PIGMAN.getId(); - } else if (newId == Entity1_16Types.EntityType.STRIDER.getId()) { - return Entity1_15Types.EntityType.MAGMA_CUBE.getId(); - } - return Protocol1_15_2To1_16.getNewEntityId(newId); - } } diff --git a/core/src/main/resources/assets/viabackwards/data/mapping-1.15to1.16.json b/core/src/main/resources/assets/viabackwards/data/mapping-1.15to1.16.json index 52627bd6..ec1cd334 100644 --- a/core/src/main/resources/assets/viabackwards/data/mapping-1.15to1.16.json +++ b/core/src/main/resources/assets/viabackwards/data/mapping-1.15to1.16.json @@ -5,8 +5,8 @@ "minecraft:basalt[axis=x]": "minecraft:gray_glazed_terracotta[facing=north]", "minecraft:basalt[axis=y]": "minecraft:gray_glazed_terracotta[facing=north]", "minecraft:basalt[axis=z]": "minecraft:gray_glazed_terracotta[facing=north]", - "minecraft:soul_fire_torch": "minecraft:torch", - "minecraft:soul_fire_wall_torch": "minecraft:wall_torch[", + "minecraft:soul_torch": "minecraft:torch", + "minecraft:soul_wall_torch": "minecraft:wall_torch[", "minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none]": "minecraft:cobblestone_wall[east=false,north=false,south=false,up=true,waterlogged=true,west=false]", "minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low]": "minecraft:cobblestone_wall[east=false,north=false,south=false,up=true,waterlogged=true,west=true]", "minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=tall]": "minecraft:cobblestone_wall[east=false,north=false,south=false,up=true,waterlogged=true,west=true]", @@ -5515,8 +5515,8 @@ "minecraft:polished_blackstone_wall[east=tall,north=tall,south=tall,up=false,waterlogged=false,west=none]": "minecraft:red_nether_brick_wall[east=true,north=true,south=true,up=false,waterlogged=false,west=false]", "minecraft:polished_blackstone_wall[east=tall,north=tall,south=tall,up=false,waterlogged=false,west=low]": "minecraft:red_nether_brick_wall[east=true,north=true,south=true,up=false,waterlogged=false,west=true]", "minecraft:polished_blackstone_wall[east=tall,north=tall,south=tall,up=false,waterlogged=false,west=tall]": "minecraft:red_nether_brick_wall[east=true,north=true,south=true,up=false,waterlogged=false,west=true]", - "minecraft:soul_fire_lantern[hanging=true]": "minecraft:lantern[hanging=true]", - "minecraft:soul_fire_lantern[hanging=false]": "minecraft:lantern[hanging=false]", + "minecraft:soul_lantern[hanging=true]": "minecraft:lantern[hanging=true]", + "minecraft:soul_lantern[hanging=false]": "minecraft:lantern[hanging=false]", "minecraft:warped_stem": "minecraft:dark_oak_log[", "minecraft:stripped_warped_stem": "minecraft:stripped_dark_oak_log[", "minecraft:warped_nylium": "minecraft:mycelium[snowy=false]", @@ -5766,7 +5766,7 @@ "id": "minecraft:gray_glazed_terracotta", "name": "1.16 Basalt" }, - "minecraft:soul_fire_torch": { + "minecraft:soul_torch": { "id": "minecraft:torch", "name": "1.16 Soul Fire Torch" }, @@ -5838,7 +5838,7 @@ "id": "minecraft:salmon_spawn_egg", "name": "1.16 Strider Spawn Egg" }, - "minecraft:soul_fire_lantern": { + "minecraft:soul_lantern": { "id": "minecraft:lantern", "name": "1.16 Soul Fire Lantern" }, @@ -6206,6 +6206,21 @@ "music.nether.crimson_forest": "music.nether", "music.nether.warped_forest": "music.nether", "entity.strider.saddle": "entity.horse.saddle", - "music_disc.pigstep": "" + "music_disc.pigstep": "", + "block.chain.break": "block.metal.break", + "block.chain.fall": "block.metal.fall", + "block.chain.hit": "block.metal.hit", + "block.chain.place": "block.metal.place", + "block.chain.step": "block.metal.step", + "block.gilded_blackstone.break": "block.metal.break", + "block.gilded_blackstone.fall": "block.metal.fall", + "block.gilded_blackstone.hit": "block.metal.hit", + "block.gilded_blackstone.place": "block.metal.place", + "block.gilded_blackstone.step": "block.metal.step", + "block.nether_gold_ore.break": "block.metal.break", + "block.nether_gold_ore.fall": "block.metal.fall", + "block.nether_gold_ore.hit": "block.metal.hit", + "block.nether_gold_ore.place": "block.metal.place", + "block.nether_gold_ore.step": "block.metal.step" } } \ No newline at end of file diff --git a/core/src/main/resources/assets/viabackwards/data/translation-mappings.json b/core/src/main/resources/assets/viabackwards/data/translation-mappings.json index eb51a262..c6c0b1d0 100644 --- a/core/src/main/resources/assets/viabackwards/data/translation-mappings.json +++ b/core/src/main/resources/assets/viabackwards/data/translation-mappings.json @@ -3,13 +3,19 @@ "selectWorld.locked": "Locked by another running instance of Minecraft", "selectWorld.access_failure": "Failed to access level", "selectWorld.delete_failure": "Failed to delete level", + "editGamerule.title": "Edit game rules", + "editGamerule.default": "Default: %s", + "selectWorld.gameRules": "Game rules", + "multiplayer.status.ping": "%s ms", "chat.queue": "[+%s pending lines]", + "options.entityDistanceScaling": "Entity Distance", + "options.entityDistancePercent": "%s%%", "options.chat.line_spacing": "Line Spacing", "options.chat.delay_none": "Chat Delay: None", "options.chat.delay": "Chat Delay: %s seconds", "block.minecraft.nether_gold_ore": "Nether Gold Ore", - "block.minecraft.soul_fire_torch": "Soul Fire Torch", - "block.minecraft.soul_fire_wall_torch": "Soul Fire Wall Torch", + "block.minecraft.soul_torch": "Soul Torch", + "block.minecraft.soul_wall_torch": "Soul Wall Torch", "block.minecraft.respawn_anchor": "Respawn Anchor", "block.minecraft.spawn.not_valid": "You have no home bed or respawn anchor, or it was obstructed", "block.minecraft.set_spawn": "Respawn point set", @@ -65,7 +71,7 @@ "block.minecraft.potted_crimson_roots": "Potted Crimson Roots", "block.minecraft.potted_warped_roots": "Potted Warped Roots", "block.minecraft.target": "Target", - "block.minecraft.soul_fire_lantern": "Soul Fire Lantern", + "block.minecraft.soul_lantern": "Soul Lantern", "block.minecraft.soul_campfire": "Soul Campfire", "block.minecraft.lodestone": "Lodestone", "block.minecraft.netherite_block": "Block of Netherite", @@ -114,11 +120,11 @@ "item.minecraft.netherite_shovel": "Netherite Shovel", "item.minecraft.netherite_sword": "Netherite Sword", "item.minecraft.warped_fungus_on_a_stick": "Warped Fungus on a Stick", - "container.upgrade": "Upgrade", + "container.upgrade": "Upgrade gear", "jigsaw_block.pool": "Target pool:", "jigsaw_block.name": "Name:", "jigsaw_block.target": "Target name:", - "jigsaw_block.levels": "Levels: ", + "jigsaw_block.levels": "Levels: %s", "jigsaw_block.generate": "Generate", "jigsaw_block.joint_label": "Joint type:", "jigsaw_block.joint.rollable": "Rollable", @@ -136,8 +142,10 @@ "death.attack.badRespawnPoint.message": "%1$s was killed by %2$s", "death.attack.badRespawnPoint.link": "Intentional Game Design", "enchantment.minecraft.soul_speed": "Soul Speed", + "gui.entity_tooltip.type": "Type: %s", "stat.minecraft.target_hit": "Targets Hit", "stat.minecraft.interact_with_smithing_table": "Interactions with Smithing Table", + "attribute.unknown": "Unknown attribute", "attribute.name.horse.jump_strength": "Horse Jump Strength", "attribute.name.zombie.spawn_reinforcements": "Zombie Reinforcements", "attribute.name.generic.max_health": "Max Health", @@ -235,6 +243,17 @@ "subtitles.particle.soul_escape": "Soul escapes", "advancements.adventure.bullseye.title": "Bullseye", "advancements.adventure.bullseye.description": "Hit the bullseye of a Target block with an arrow", + "argument.uuid.invalid": "Invalid UUID", + "commands.attribute.failed.entity": "%s is not a valid entity for this command", + "commands.attribute.failed.no_attribute": "Entity %s has no attribute %s", + "commands.attribute.failed.no_modifier": "Attribute %s for entity %s has no modifier %s", + "commands.attribute.failed.modifier_already_present": "Modifier %s is already present on attribute %s for entity %s", + "commands.attribute.value.get.success": "Value of attribute %s for entity %s is %s", + "commands.attribute.base_value.get.success": "Base value of attribute %s for entity %s is %s", + "commands.attribute.base_value.set.success": "Base value for attribute %s for entity %s set to %s", + "commands.attribute.modifier.add.success": "Added modifier %s to attribute %s for entity %s", + "commands.attribute.modifier.remove.success": "Removed modifier %s from attribute %s for entity %s", + "commands.attribute.modifier.value.get.success": "Value of modifier %s on attribute %s for entity %s is %s", "commands.locatebiome.success": "The nearest %s is at %s (%s blocks away)", "commands.teleport.invalidPosition": "Invalid position for teleport", "commands.locatebiome.notFound": "Could not find a %s within reasonable distance", @@ -244,7 +263,52 @@ "biome.minecraft.soul_sand_valley": "Soul Sand Valley", "biome.minecraft.warped_forest": "Warped Forest", "biome.minecraft.crimson_forest": "Crimson Forest", - "biome.minecraft.basalt_deltas": "Basalt Deltas" + "biome.minecraft.basalt_deltas": "Basalt Deltas", + "gamerule.announceAdvancements": "Announce advancements", + "gamerule.commandBlockOutput": "Broadcast command block output", + "gamerule.disableElytraMovementCheck": "Disable Elytra movement check", + "gamerule.disableRaids": "Disable raids", + "gamerule.doDaylightCycle": "Advance in-game time", + "gamerule.doEntityDrops": "Drop entity equipment", + "gamerule.doEntityDrops.description": "Controls drops from minecarts (including inventories), item frames, boats, etc.", + "gamerule.doFireTick": "Update fire", + "gamerule.doImmediateRespawn": "Respawn immediately", + "gamerule.doInsomnia": "Spawn phantoms", + "gamerule.doLimitedCrafting": "Require recipe for crafting", + "gamerule.doLimitedCrafting.description": "If enabled, players will be able to craft only unlocked recipes", + "gamerule.doMobLoot": "Drop mob loot", + "gamerule.doMobLoot.description": "Controls resource drops, including experience orbs", + "gamerule.doMobSpawning": "Spawn mobs", + "gamerule.doMobSpawning.description": "Some entities might have separate rules", + "gamerule.doPatrolSpawning": "Spawn pillager patrols", + "gamerule.doTileDrops": "Drop blocks", + "gamerule.doTileDrops.description": "Controls resource drops, including experience orbs", + "gamerule.doTraderSpawning": "Spawn wandering traders", + "gamerule.doWeatherCycle": "Update weather", + "gamerule.drowningDamage": "Deal drowning damage", + "gamerule.fallDamage": "Deal fall damage", + "gamerule.fireDamage": "Deal fire damage", + "gamerule.keepInventory": "Keep inventory after death", + "gamerule.logAdminCommands": "Broadcast admin commands", + "gamerule.maxCommandChainLength": "Command chain size limit", + "gamerule.maxCommandChainLength.description": "Applies to command block chains and functions", + "gamerule.maxEntityCramming": "Entity cramming threshold", + "gamerule.mobGriefing": "Allow destructive mob actions", + "gamerule.naturalRegeneration": "Regenerate health", + "gamerule.randomTickSpeed": "Random tick speed rate", + "gamerule.reducedDebugInfo": "Reduce debug info", + "gamerule.reducedDebugInfo.description": "Limits contents of debug screen", + "gamerule.sendCommandFeedback": "Send command feedback", + "gamerule.showDeathMessages": "Show death messages", + "gamerule.spawnRadius": "Respawn location radius", + "gamerule.spectatorsGenerateChunks": "Allow spectators to generate terrain", + "gamerule.category.chat": "Chat", + "gamerule.category.spawning": "Spawning", + "gamerule.category.updates": "World updates", + "gamerule.category.drops": "Drops", + "gamerule.category.mobs": "Mobs", + "gamerule.category.player": "Player", + "gamerule.category.misc": "Miscellaneous" }, "1.15": { "narration.suggestion.tooltip": "Selected suggestion %d out of %d: %s (%s)",