diff --git a/worldedit-forge/build.gradle b/worldedit-forge/build.gradle index 3885ff369..9b033cab8 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -14,7 +14,7 @@ buildscript { apply plugin: 'net.minecraftforge.gradle' def minecraftVersion = "1.13" -def forgeVersion = "24.0.32-1.13-pre" +def forgeVersion = "24.0.44-1.13-pre" dependencies { compile project(':worldedit-core') @@ -29,6 +29,8 @@ targetCompatibility = 1.8 minecraft { mappings channel: 'snapshot', version: '20180921-1.13' + + accessTransformer = file('worldedit_at.cfg') } project.archivesBaseName = "${project.archivesBaseName}-mc${minecraftVersion}" diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java index f28e35a0b..a3523ddb6 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeAdapter.java @@ -33,12 +33,12 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import net.minecraft.block.properties.IProperty; -import net.minecraft.block.properties.PropertyBool; -import net.minecraft.block.properties.PropertyDirection; -import net.minecraft.block.properties.PropertyEnum; -import net.minecraft.block.properties.PropertyInteger; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; +import net.minecraft.state.DirectionProperty; +import net.minecraft.state.IProperty; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.biome.Biome; @@ -105,20 +105,20 @@ final class ForgeAdapter { } public static Property adaptProperty(IProperty property) { - if (property instanceof PropertyBool) { - return new BooleanProperty(property.getName(), ImmutableList.copyOf(((PropertyBool) property).getAllowedValues())); + if (property instanceof net.minecraft.state.BooleanProperty) { + return new BooleanProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.state.BooleanProperty) property).getAllowedValues())); } - if (property instanceof PropertyInteger) { - return new IntegerProperty(property.getName(), ImmutableList.copyOf(((PropertyInteger) property).getAllowedValues())); + if (property instanceof net.minecraft.state.IntegerProperty) { + return new IntegerProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.state.IntegerProperty) property).getAllowedValues())); } - if (property instanceof PropertyDirection) { - return new DirectionalProperty(property.getName(), ((PropertyDirection) property).getAllowedValues().stream() + if (property instanceof DirectionProperty) { + return new DirectionalProperty(property.getName(), ((DirectionProperty) property).getAllowedValues().stream() .map(ForgeAdapter::adaptEnumFacing) .collect(Collectors.toList())); } - if (property instanceof PropertyEnum) { - return new EnumProperty(property.getName(), ((PropertyEnum) property).getAllowedValues().stream() - .map(e -> e.getName()) + if (property instanceof net.minecraft.state.EnumProperty) { + return new EnumProperty(property.getName(), ((net.minecraft.state.EnumProperty) property).getAllowedValues().stream() + .map(IStringSerializable::getName) .collect(Collectors.toList())); } return new IPropertyAdapter<>(property); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBiomeRegistry.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBiomeRegistry.java index 986a3afc2..cbe2102c9 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBiomeRegistry.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBiomeRegistry.java @@ -52,7 +52,7 @@ class ForgeBiomeRegistry implements BiomeRegistry { @Override public String getName() { - return biome.getBiomeName(); + return biome.getDisplayName().getString(); } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java index ddf3762bb..f77dc2304 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java @@ -26,7 +26,7 @@ import com.sk89q.worldedit.world.registry.BundledBlockRegistry; import net.minecraft.block.Block; import net.minecraft.block.material.Material; -import net.minecraft.block.properties.IProperty; +import net.minecraft.state.IProperty; import net.minecraft.util.ResourceLocation; import java.util.Collection; @@ -43,7 +43,7 @@ public class ForgeBlockRegistry extends BundledBlockRegistry { @Nullable @Override public String getName(BlockType blockType) { - return Block.REGISTRY.getObject(new ResourceLocation(blockType.getId())).getLocalizedName(); + return Block.REGISTRY.get(new ResourceLocation(blockType.getId())).getNameTextComponent().getFormattedText(); } @Override @@ -57,7 +57,7 @@ public class ForgeBlockRegistry extends BundledBlockRegistry { Map> map = new TreeMap<>(); Collection> propertyKeys = Block.getBlockFromName(blockType.getId()) .getDefaultState() - .getPropertyKeys(); + .getProperties(); for (IProperty key : propertyKeys) { map.put(key.getName(), ForgeAdapter.adaptProperty(key)); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java index e4b391fe0..1c428e0c1 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java @@ -52,7 +52,7 @@ class ForgeEntity implements Entity { String id = EntityList.getEntityString(entity); if (id != null) { NBTTagCompound tag = new NBTTagCompound(); - entity.writeToNBT(tag); + entity.writeWithoutTypeId(tag); return new BaseEntity(EntityTypes.get(id), NBTConverter.fromNative(tag)); } else { return null; @@ -96,7 +96,7 @@ class ForgeEntity implements Entity { public boolean remove() { net.minecraft.entity.Entity entity = entityRef.get(); if (entity != null) { - entity.setDead(); + entity.remove(); } return true; } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index a20abd100..65705004c 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -41,10 +41,10 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.server.SPacketCustomPayload; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; -import net.minecraftforge.fml.common.registry.ForgeRegistries; import java.util.UUID; @@ -69,12 +69,12 @@ public class ForgePlayer extends AbstractPlayerActor { @Override public BaseItemStack getItemInHand(HandSide handSide) { ItemStack is = this.player.getHeldItem(handSide == HandSide.MAIN_HAND ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND); - return new BaseItemStack(ItemTypes.get(ForgeRegistries.ITEMS.getKey(is.getItem()).toString())); + return new BaseItemStack(ItemTypes.get(Item.REGISTRY.getKey(is.getItem()).toString())); } @Override public String getName() { - return this.player.getName(); + return this.player.getName().getFormattedText(); } @Override @@ -105,8 +105,7 @@ public class ForgePlayer extends AbstractPlayerActor { @Override public void giveItem(BaseItemStack itemStack) { - this.player.inventory.addItemStackToInventory( - new ItemStack(Item.getByNameOrId(itemStack.getType().getId()), itemStack.getAmount(), 0)); + this.player.inventory.addItemStackToInventory(new ItemStack(Item.REGISTRY.get(new ResourceLocation(itemStack.getType().getId())), itemStack.getAmount(), null)); } @Override @@ -117,7 +116,7 @@ public class ForgePlayer extends AbstractPlayerActor { send = send + "|" + StringUtil.joinString(params, "|"); } PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET))); - SPacketCustomPayload packet = new SPacketCustomPayload(ForgeWorldEdit.CUI_PLUGIN_CHANNEL, buffer); + SPacketCustomPayload packet = new SPacketCustomPayload(new ResourceLocation(ForgeWorldEdit.CUI_PLUGIN_CHANNEL), buffer); this.player.connection.sendPacket(packet); } @@ -197,7 +196,7 @@ public class ForgePlayer extends AbstractPlayerActor { @Override public SessionKey getSessionKey() { - return new SessionKeyImpl(player.getUniqueID(), player.getName()); + return new SessionKeyImpl(player.getUniqueID(), player.getName().getString()); } private static class SessionKeyImpl implements SessionKey { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 09fcc4241..13205b726 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -51,15 +51,7 @@ import com.sk89q.worldedit.world.weather.WeatherType; import com.sk89q.worldedit.world.weather.WeatherTypes; import net.minecraft.block.Block; import net.minecraft.block.BlockLeaves; -import net.minecraft.block.BlockOldLeaf; -import net.minecraft.block.BlockOldLog; -import net.minecraft.block.BlockPlanks; -import net.minecraft.block.properties.IProperty; -import net.minecraft.block.properties.PropertyDirection; -import net.minecraft.block.properties.PropertyEnum; -import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.EntityList; import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; @@ -67,6 +59,9 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; +import net.minecraft.state.DirectionProperty; +import net.minecraft.state.EnumProperty; +import net.minecraft.state.IProperty; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; @@ -77,6 +72,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.storage.AnvilSaveHandler; @@ -116,9 +112,9 @@ public class ForgeWorld extends AbstractWorld { private static final Random random = new Random(); private static final int UPDATE = 1, NOTIFY = 2; - private static final IBlockState JUNGLE_LOG = Blocks.LOG.getDefaultState().withProperty(BlockOldLog.VARIANT, BlockPlanks.EnumType.JUNGLE); - private static final IBlockState JUNGLE_LEAF = Blocks.LEAVES.getDefaultState().withProperty(BlockOldLeaf.VARIANT, BlockPlanks.EnumType.JUNGLE).withProperty(BlockLeaves.CHECK_DECAY, Boolean.valueOf(false)); - private static final IBlockState JUNGLE_SHRUB = Blocks.LEAVES.getDefaultState().withProperty(BlockOldLeaf.VARIANT, BlockPlanks.EnumType.OAK).withProperty(BlockLeaves.CHECK_DECAY, Boolean.valueOf(false)); + private static final IBlockState JUNGLE_LOG = Blocks.JUNGLE_LOG.getDefaultState(); + private static final IBlockState JUNGLE_LEAF = Blocks.JUNGLE_LEAVES.getDefaultState().with(BlockLeaves.PERSISTENT, Boolean.TRUE); + private static final IBlockState JUNGLE_SHRUB = Blocks.OAK_LEAVES.getDefaultState().with(BlockLeaves.PERSISTENT, Boolean.TRUE); private final WeakReference worldRef; @@ -178,7 +174,7 @@ public class ForgeWorld extends AbstractWorld { int z = position.getBlockZ(); // First set the block - Chunk chunk = world.getChunkFromChunkCoords(x >> 4, z >> 4); + Chunk chunk = world.getChunk(x >> 4, z >> 4); BlockPos pos = new BlockPos(x, y, z); IBlockState old = chunk.getBlockState(pos); Block mcBlock = Block.getBlockFromName(block.getBlockType().getId()); @@ -224,17 +220,17 @@ public class ForgeWorld extends AbstractWorld { IProperty property = stateContainer.getProperty(state.getKey().getName()); Comparable value = (Comparable) state.getValue(); // we may need to adapt this value, depending on the source prop - if (property instanceof PropertyDirection) { + if (property instanceof DirectionProperty) { Direction dir = (Direction) value; value = ForgeAdapter.adapt(dir); - } else if (property instanceof PropertyEnum) { + } else if (property instanceof EnumProperty) { String enumName = (String) value; - value = ((PropertyEnum) property).parseValue((String) value).or(() -> { + value = ((EnumProperty) property).parseValue((String) value).orElseGet(() -> { throw new IllegalStateException("Enum property " + property.getName() + " does not contain " + enumName); }); } - newState = newState.withProperty(property, value); + newState = newState.with(property, value); } return newState; } @@ -271,7 +267,7 @@ public class ForgeWorld extends AbstractWorld { checkNotNull(position); checkNotNull(biome); - Chunk chunk = getWorld().getChunkFromBlockCoords(new BlockPos(position.getBlockX(), 0, position.getBlockZ())); + Chunk chunk = getWorld().getChunk(new BlockPos(position.getBlockX(), 0, position.getBlockZ())); if (chunk.isLoaded()) { chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = (byte) Biome.getIdForBiome(ForgeAdapter.adapt(biome)); return true; @@ -282,12 +278,12 @@ public class ForgeWorld extends AbstractWorld { @Override public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { - Item nativeItem = Item.getByNameOrId(item.getType().getId()); + Item nativeItem = Item.REGISTRY.get(new ResourceLocation(item.getType().getId())); ItemStack stack = null; if (item.getNbtData() == null) { - stack = new ItemStack(nativeItem, 1, 0); + stack = new ItemStack(nativeItem, 1); } else { - stack = new ItemStack(nativeItem, 1, 0, NBTConverter.toNative(item.getNbtData())); + stack = new ItemStack(nativeItem, 1, NBTConverter.toNative(item.getNbtData())); } World world = getWorld(); EnumActionResult used = stack.onItemUse(new WorldEditFakePlayer((WorldServer) world), world, ForgeAdapter.toBlockPos(position), @@ -333,16 +329,15 @@ public class ForgeWorld extends AbstractWorld { WorldServer originalWorld = (WorldServer) getWorld(); MinecraftServer server = originalWorld.getMinecraftServer(); - AnvilSaveHandler saveHandler = new AnvilSaveHandler(saveFolder, - originalWorld.getSaveHandler().getWorldDirectory().getName(), true, server.getDataFixer()); + AnvilSaveHandler saveHandler = new AnvilSaveHandler(saveFolder, originalWorld.getSaveHandler().getWorldDirectory().getName(), true, server.getDataFixer()); World freshWorld = new WorldServer(server, saveHandler, originalWorld.getWorldInfo(), - originalWorld.provider.getDimension(), originalWorld.profiler).init(); + originalWorld.dimension.getId(), originalWorld.profiler).init(); // Pre-gen all the chunks // We need to also pull one more chunk in every direction CuboidRegion expandedPreGen = new CuboidRegion(region.getMinimumPoint().subtract(16, 0, 16), region.getMaximumPoint().add(16, 0, 16)); for (BlockVector2 chunk : expandedPreGen.getChunks()) { - freshWorld.getChunkFromChunkCoords(chunk.getBlockX(), chunk.getBlockZ()); + freshWorld.getChunk(chunk.getBlockX(), chunk.getBlockZ()); } ForgeWorld from = new ForgeWorld(freshWorld); @@ -354,8 +349,8 @@ public class ForgeWorld extends AbstractWorld { throw new RuntimeException(e); } finally { saveFolder.delete(); - DimensionManager.setWorld(originalWorld.provider.getDimension(), null, server); - DimensionManager.setWorld(originalWorld.provider.getDimension(), originalWorld, server); + DimensionManager.setWorld(originalWorld.dimension.getId(), null, server); + DimensionManager.setWorld(originalWorld.dimension.getId(), originalWorld, server); } return true; @@ -396,7 +391,7 @@ public class ForgeWorld extends AbstractWorld { @Override public void checkLoadedChunk(BlockVector3 pt) { - getWorld().getChunkFromBlockCoords(ForgeAdapter.toBlockPos(pt)); + getWorld().getChunk(ForgeAdapter.toBlockPos(pt)); } @Override @@ -408,7 +403,7 @@ public class ForgeWorld extends AbstractWorld { public void fixLighting(Iterable chunks) { World world = getWorld(); for (BlockVector2 chunk : chunks) { - world.getChunkFromChunkCoords(chunk.getBlockX(), chunk.getBlockZ()).resetRelightChecks(); + world.getChunk(chunk.getBlockX(), chunk.getBlockZ()).resetRelightChecks(); } } @@ -439,7 +434,7 @@ public class ForgeWorld extends AbstractWorld { if (info.isRaining()) { return info.getRainTime(); } - return info.getCleanWeatherTime(); + return info.getClearWeatherTime(); } @Override @@ -451,17 +446,17 @@ public class ForgeWorld extends AbstractWorld { public void setWeather(WeatherType weatherType, long duration) { WorldInfo info = getWorld().getWorldInfo(); if (WeatherTypes.THUNDER_STORM.equals(weatherType)) { - info.setCleanWeatherTime(0); + info.setClearWeatherTime(0); info.setThundering(true); info.setThunderTime((int) duration); } else if (WeatherTypes.RAIN.equals(weatherType)) { - info.setCleanWeatherTime(0); + info.setClearWeatherTime(0); info.setRaining(true); info.setRainTime((int) duration); } else if (WeatherTypes.CLEAR.equals(weatherType)) { info.setRaining(false); info.setThundering(false); - info.setCleanWeatherTime((int) duration); + info.setClearWeatherTime((int) duration); } } @@ -476,7 +471,7 @@ public class ForgeWorld extends AbstractWorld { BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); IBlockState mcState = world.getBlockState(pos); - BlockType blockType = BlockType.REGISTRY.get(Block.REGISTRY.getNameForObject(mcState.getBlock()).toString()); + BlockType blockType = BlockType.REGISTRY.get(Block.REGISTRY.getKey(mcState.getBlock()).toString()); return blockType.getState(adaptProperties(blockType, mcState.getProperties())); } @@ -484,9 +479,9 @@ public class ForgeWorld extends AbstractWorld { Map, Object> props = new TreeMap<>(Comparator.comparing(Property::getName)); for (Map.Entry, Comparable> prop : mcProps.entrySet()) { Object value = prop.getValue(); - if (prop.getKey() instanceof PropertyDirection) { + if (prop.getKey() instanceof DirectionProperty) { value = ForgeAdapter.adaptEnumFacing((EnumFacing) value); - } else if (prop.getKey() instanceof PropertyEnum) { + } else if (prop.getKey() instanceof EnumProperty) { value = ((IStringSerializable) value).getName(); } props.put(block.getProperty(prop.getKey().getName()), value); @@ -559,7 +554,7 @@ public class ForgeWorld extends AbstractWorld { for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.removeTag(name); } - createdEntity.readFromNBT(tag); + createdEntity.read(tag); } createdEntity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/IPropertyAdapter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/IPropertyAdapter.java index 0ac900a55..e024f6e93 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/IPropertyAdapter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/IPropertyAdapter.java @@ -21,13 +21,12 @@ package com.sk89q.worldedit.forge; import static com.google.common.base.Preconditions.checkArgument; -import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.registry.state.Property; - -import net.minecraft.block.properties.IProperty; +import net.minecraft.state.IProperty; import java.util.List; +import java.util.Optional; class IPropertyAdapter> implements Property { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java index 0992d3d4f..f05fbef47 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/NBTConverter.java @@ -32,7 +32,7 @@ import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.ShortTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.INBTBase; import net.minecraft.nbt.NBTTagByte; import net.minecraft.nbt.NBTTagByteArray; import net.minecraft.nbt.NBTTagCompound; @@ -62,7 +62,7 @@ final class NBTConverter { private NBTConverter() { } - public static NBTBase toNative(Tag tag) { + public static INBTBase toNative(Tag tag) { if (tag instanceof IntArrayTag) { return toNative((IntArrayTag) tag); @@ -111,7 +111,7 @@ final class NBTConverter { if (child instanceof EndTag) { continue; } - list.appendTag(toNative(child)); + list.add(toNative(child)); } return list; } @@ -157,7 +157,7 @@ final class NBTConverter { return new NBTTagDouble(tag.getValue()); } - public static Tag fromNative(NBTBase other) { + public static Tag fromNative(INBTBase other) { if (other instanceof NBTTagIntArray) { return fromNative((NBTTagIntArray) other); @@ -207,9 +207,9 @@ final class NBTConverter { other = other.copy(); List list = new ArrayList<>(); Class listClass = StringTag.class; - int tags = other.tagCount(); + int tags = other.size(); for (int i = 0; i < tags; i++) { - Tag child = fromNative(other.removeTag(0)); + Tag child = fromNative(other.remove(0)); list.add(child); listClass = child.getClass(); } @@ -242,7 +242,7 @@ final class NBTConverter { } public static CompoundTag fromNative(NBTTagCompound other) { - Set tags = other.getKeySet(); + Set tags = other.keySet(); Map map = new HashMap<>(); for (String tagName : tags) { map.put(tagName, fromNative(other.getTag(tagName)));