Upstream merge of TranslationManager and ResourceLoader

This commit is contained in:
MattBDev 2020-08-24 12:38:30 -04:00
parent 1bef8901bf
commit fd336feb46
16 changed files with 489 additions and 246 deletions

View File

@ -14,7 +14,21 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import net.jpountz.util.UnsafeUtils; import net.jpountz.util.UnsafeUtils;
import net.minecraft.server.v1_16_R2.*; import net.minecraft.server.v1_16_R2.Block;
import net.minecraft.server.v1_16_R2.Chunk;
import net.minecraft.server.v1_16_R2.ChunkCoordIntPair;
import net.minecraft.server.v1_16_R2.ChunkSection;
import net.minecraft.server.v1_16_R2.DataBits;
import net.minecraft.server.v1_16_R2.DataPalette;
import net.minecraft.server.v1_16_R2.DataPaletteBlock;
import net.minecraft.server.v1_16_R2.DataPaletteLinear;
import net.minecraft.server.v1_16_R2.GameProfileSerializer;
import net.minecraft.server.v1_16_R2.IBlockData;
import net.minecraft.server.v1_16_R2.PacketPlayOutLightUpdate;
import net.minecraft.server.v1_16_R2.PlayerChunk;
import net.minecraft.server.v1_16_R2.PlayerChunkMap;
import net.minecraft.server.v1_16_R2.World;
import net.minecraft.server.v1_16_R2.WorldServer;
import org.bukkit.craftbukkit.v1_16_R2.CraftChunk; import org.bukkit.craftbukkit.v1_16_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_16_R2.CraftWorld; import org.bukkit.craftbukkit.v1_16_R2.CraftWorld;
import sun.misc.Unsafe; import sun.misc.Unsafe;
@ -34,20 +48,20 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
/* /*
NMS fields NMS fields
*/ */
public final static Field fieldBits; public static final Field fieldBits;
public final static Field fieldPalette; public static final Field fieldPalette;
public final static Field fieldSize; public static final Field fieldSize;
public final static Field fieldBitsPerEntry; public static final Field fieldBitsPerEntry;
public final static Field fieldFluidCount; public static final Field fieldFluidCount;
public final static Field fieldTickingBlockCount; public static final Field fieldTickingBlockCount;
public final static Field fieldNonEmptyBlockCount; public static final Field fieldNonEmptyBlockCount;
private final static Field fieldDirtyCount; private static final Field fieldDirtyCount;
private final static Field fieldDirtyBits; private static final Field fieldDirtyBits;
private final static MethodHandle methodGetVisibleChunk; private static final MethodHandle methodGetVisibleChunk;
private static final int CHUNKSECTION_BASE; private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT; private static final int CHUNKSECTION_SHIFT;
@ -128,17 +142,17 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
} }
} }
public static Chunk ensureLoaded(World nmsWorld, int X, int Z) { public static Chunk ensureLoaded(World nmsWorld, int chunkX, int chunkZ) {
Chunk nmsChunk = nmsWorld.getChunkProvider().getChunkAt(X, Z, false); Chunk nmsChunk = nmsWorld.getChunkProvider().getChunkAt(chunkX, chunkZ, false);
if (nmsChunk != null) { if (nmsChunk != null) {
return nmsChunk; return nmsChunk;
} }
if (Fawe.isMainThread()) { if (Fawe.isMainThread()) {
return nmsWorld.getChunkAt(X, Z); return nmsWorld.getChunkAt(chunkX, chunkZ);
} }
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
CraftWorld craftWorld = nmsWorld.getWorld(); CraftWorld craftWorld = nmsWorld.getWorld();
CompletableFuture<org.bukkit.Chunk> future = craftWorld.getChunkAtAsync(X, Z, true); CompletableFuture<org.bukkit.Chunk> future = craftWorld.getChunkAtAsync(chunkX, chunkZ, true);
try { try {
CraftChunk chunk = (CraftChunk) future.get(); CraftChunk chunk = (CraftChunk) future.get();
return chunk.getHandle(); return chunk.getHandle();
@ -147,20 +161,20 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
} }
} }
// TODO optimize // TODO optimize
return TaskManager.IMP.sync(() -> nmsWorld.getChunkAt(X, Z)); return TaskManager.IMP.sync(() -> nmsWorld.getChunkAt(chunkX, chunkZ));
} }
public static PlayerChunk getPlayerChunk(WorldServer nmsWorld, final int cx, final int cz) { public static PlayerChunk getPlayerChunk(WorldServer nmsWorld, final int chunkX, final int chunkZ) {
PlayerChunkMap chunkMap = nmsWorld.getChunkProvider().playerChunkMap; PlayerChunkMap chunkMap = nmsWorld.getChunkProvider().playerChunkMap;
try { try {
return (PlayerChunk)methodGetVisibleChunk.invoke(chunkMap, ChunkCoordIntPair.pair(cx, cz)); return (PlayerChunk)methodGetVisibleChunk.invoke(chunkMap, ChunkCoordIntPair.pair(chunkX, chunkZ));
} catch (Throwable thr) { } catch (Throwable thr) {
throw new RuntimeException(thr); throw new RuntimeException(thr);
} }
} }
public static void sendChunk(WorldServer nmsWorld, int X, int Z, int mask, boolean lighting) { public static void sendChunk(WorldServer nmsWorld, int chunkX, int chunkZ, int mask, boolean lighting) {
PlayerChunk playerChunk = getPlayerChunk(nmsWorld, X, Z); PlayerChunk playerChunk = getPlayerChunk(nmsWorld, chunkX, chunkZ);
if (playerChunk == null) { if (playerChunk == null) {
return; return;
} }
@ -181,7 +195,7 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
fieldDirtyCount.set(playerChunk, 64); fieldDirtyCount.set(playerChunk, 64);
if (lighting) { if (lighting) {
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(X, Z); ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
boolean trustEdges = false; //Added in 1.16.1 Not sure what it does. boolean trustEdges = false; //Added in 1.16.1 Not sure what it does.
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges); PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> { playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {

View File

@ -1,8 +1,26 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.world.registry.BundledItemRegistry; import com.sk89q.worldedit.world.registry.BundledItemRegistry;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
@ -26,6 +26,7 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.AbstractPlatform;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
@ -41,7 +42,6 @@ import org.bukkit.World;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandManager;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.EnumMap; import java.util.EnumMap;
@ -50,27 +50,30 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.sk89q.worldedit.util.formatting.WorldEditText.reduceToText; import static com.sk89q.worldedit.util.formatting.WorldEditText.reduceToText;
public class BukkitServerInterface implements MultiUserPlatform { public class BukkitServerInterface extends AbstractPlatform implements MultiUserPlatform {
public Server server;
public WorldEditPlugin plugin; public final Server server;
private CommandRegistration dynamicCommands; public final WorldEditPlugin plugin;
private final CommandRegistration dynamicCommands;
private final LazyReference<Watchdog> watchdog;
private boolean hookingEvents; private boolean hookingEvents;
private final LazyReference<Watchdog> watchdog = LazyReference.from(() -> {
if (plugin.getBukkitImplAdapter() != null) {
return plugin.getBukkitImplAdapter().supportsWatchdog()
? new BukkitWatchdog(plugin.getBukkitImplAdapter())
: null;
}
return null;
});
public BukkitServerInterface(WorldEditPlugin plugin, Server server) { public BukkitServerInterface(WorldEditPlugin plugin, Server server) {
this.plugin = plugin; this.plugin = plugin;
this.server = server; this.server = server;
dynamicCommands = new CommandRegistration(plugin); this.dynamicCommands = new CommandRegistration(plugin);
this.watchdog = LazyReference.from(() -> {
if (plugin.getBukkitImplAdapter() != null) {
return plugin.getBukkitImplAdapter().supportsWatchdog()
? new BukkitWatchdog(plugin.getBukkitImplAdapter())
: null;
}
return null;
});
} }
CommandRegistration getDynamicCommands() { CommandRegistration getDynamicCommands() {
@ -107,6 +110,7 @@ public class BukkitServerInterface implements MultiUserPlatform {
if (!type.startsWith("minecraft:")) { if (!type.startsWith("minecraft:")) {
return false; return false;
} }
@SuppressWarnings("deprecation")
final EntityType entityType = EntityType.fromName(type.substring(10)); final EntityType entityType = EntityType.fromName(type.substring(10));
return entityType != null && entityType.isAlive(); return entityType != null && entityType.isAlive();
} }

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit; package com.sk89q.worldedit;
@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -172,11 +173,6 @@ public abstract class LocalConfiguration {
*/ */
public abstract void load(); public abstract void load();
/**
*
* @param holder
* @return true if block is not permitted
*/
public boolean checkDisallowedBlocks(BlockStateHolder holder) { public boolean checkDisallowedBlocks(BlockStateHolder holder) {
if (disallowedBlocks.isEmpty()) { if (disallowedBlocks.isEmpty()) {
return false; return false;
@ -199,9 +195,20 @@ public abstract class LocalConfiguration {
* Get the working directory to work from. * Get the working directory to work from.
* *
* @return a working directory * @return a working directory
* @deprecated Use {@link LocalConfiguration#getWorkingDirectoryPath()}
*/ */
@Deprecated
public File getWorkingDirectory() { public File getWorkingDirectory() {
return new File("."); return getWorkingDirectoryPath().toFile();
}
/**
* Get the working directory to work from.
*
* @return a working directory
*/
public Path getWorkingDirectoryPath() {
return Paths.get(".");
} }
public void initializeSnapshotConfiguration(String directory, boolean experimental) { public void initializeSnapshotConfiguration(String directory, boolean experimental) {
@ -240,7 +247,7 @@ public abstract class LocalConfiguration {
data = Byte.parseByte(splitter[1]); data = Byte.parseByte(splitter[1]);
} }
item = LegacyMapper.getInstance().getItemFromLegacy(id, data).getId(); item = LegacyMapper.getInstance().getItemFromLegacy(id, data).getId();
} catch (Throwable e) { } catch (Throwable ignored) {
} }
return item; return item;

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit; package com.sk89q.worldedit;
@ -54,6 +54,7 @@ import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors; import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
@ -119,7 +120,10 @@ public final class WorldEdit {
private final SessionManager sessions = new SessionManager(this); private final SessionManager sessions = new SessionManager(this);
private final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20, "WorldEdit Task Executor - %s")); private final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20, "WorldEdit Task Executor - %s"));
private final Supervisor supervisor = new SimpleSupervisor(); private final Supervisor supervisor = new SimpleSupervisor();
private final TranslationManager translationManager = new TranslationManager(this); private final LazyReference<TranslationManager> translationManager =
LazyReference.from(() -> new TranslationManager(
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.CONFIGURATION).getResourceLoader()
));
private final BlockFactory blockFactory = new BlockFactory(this); private final BlockFactory blockFactory = new BlockFactory(this);
private final ItemFactory itemFactory = new ItemFactory(this); private final ItemFactory itemFactory = new ItemFactory(this);
@ -242,7 +246,7 @@ public final class WorldEdit {
* @return the translation manager * @return the translation manager
*/ */
public TranslationManager getTranslationManager() { public TranslationManager getTranslationManager() {
return translationManager; return translationManager.getValue();
} }
/** /**
@ -432,14 +436,27 @@ public final class WorldEdit {
* *
* @param path the subpath under the working directory * @param path the subpath under the working directory
* @return a working directory * @return a working directory
* @deprecated Use {@link WorldEdit#getWorkingDirectoryPath(String)} instead
*/ */
@Deprecated
public File getWorkingDirectoryFile(String path) { public File getWorkingDirectoryFile(String path) {
File f = new File(path); return getWorkingDirectoryPath(path).toFile();
if (f.isAbsolute()) { }
return f;
/**
* Get a file relative to the defined working directory. If the specified
* path is absolute, then the working directory is not used.
*
* @param path the subpath under the working directory
* @return a working directory
*/
public Path getWorkingDirectoryPath(String path) {
Path p = Paths.get(path);
if (p.isAbsolute()) {
return p;
} }
return new File(getConfiguration().getWorkingDirectory(), path); return getConfiguration().getWorkingDirectoryPath().resolve(path);
} }
/** /**
@ -769,6 +786,7 @@ public final class WorldEdit {
/** /**
* Get a factory for {@link EditSession}s. * Get a factory for {@link EditSession}s.
*/ */
@Deprecated
public EditSessionFactory getEditSessionFactory() { public EditSessionFactory getEditSessionFactory() {
return editSessionFactory; return editSessionFactory;
} }

View File

@ -3,22 +3,25 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.extension.platform; package com.sk89q.worldedit.extension.platform;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.util.io.ResourceLoader;
import com.sk89q.worldedit.util.io.WorldEditResourceLoader;
import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -30,6 +33,13 @@ import java.util.List;
*/ */
public abstract class AbstractPlatform implements Platform { public abstract class AbstractPlatform implements Platform {
private final ResourceLoader resourceLoader = new WorldEditResourceLoader(WorldEdit.getInstance());
@Override
public ResourceLoader getResourceLoader() {
return resourceLoader;
}
@Override @Override
public int schedule(long delay, long period, Runnable task) { public int schedule(long delay, long period, Runnable task) {
return -1; return -1;

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.extension.platform; package com.sk89q.worldedit.extension.platform;
@ -22,6 +22,7 @@ package com.sk89q.worldedit.extension.platform;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.io.ResourceLoader;
import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.Registries; import com.sk89q.worldedit.world.registry.Registries;
@ -40,6 +41,13 @@ import javax.annotation.Nullable;
*/ */
public interface Platform { public interface Platform {
/**
* Return the resource loader.
*
* @return The resource loader
*/
ResourceLoader getResourceLoader();
/** /**
* Gets the registry holder. * Gets the registry holder.
* *

View File

@ -3,52 +3,79 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.util.io; package com.sk89q.worldedit.util.io;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.nio.file.Path;
import javax.annotation.Nullable;
public class ResourceLoader { import static com.google.common.base.Preconditions.checkArgument;
private ResourceLoader() { /**
* An abstract loader that handles loading resources from bundled URLs or local
* files.
*/
public interface ResourceLoader {
/**
* Gets the bundled resource URL by name, relative to the provided class.
*
* <p>
* The path name <b>must not</b> start with {@code /}.
* </p>
*
* @param clazz The class to search relative to
* @param pathName The path name
* @return The URL to this bundled resource
* @throws IOException if an IO issue occurs
*/
@Nullable
default URL getResource(Class<?> clazz, String pathName) throws IOException {
checkArgument(!pathName.startsWith("/"), "pathName must not start with /");
String qualifiedName = clazz.getName().substring(0, clazz.getName().lastIndexOf('.'))
.replace(".", "/") + "/" + pathName;
return getRootResource(qualifiedName);
} }
private static URL getResourceForgeHack(String location) throws IOException { /**
try { * Gets the bundled resource URL by name.
return new URL("modjar://worldedit/" + location); *
} catch (Exception e) { * <p>
throw new IOException("Could not find " + location); * The path name <b>must not</b> start with {@code /}. It is always
} * absolute.
* </p>
*
* @param pathName The path name
* @return The URL to this bundled resource
* @throws IOException if an IO issue occurs
*/
@Nullable
default URL getRootResource(String pathName) throws IOException {
checkArgument(!pathName.startsWith("/"), "pathName must not start with /");
return this.getClass().getClassLoader().getResource(pathName);
} }
public static URL getResource(Class clazz, String name) throws IOException { /**
URL url = clazz.getResource(name); * Gets the {@link Path} reference to this local resource. The file may not
if (url == null) { * exist.
return getResourceForgeHack(clazz.getName().substring(0, clazz.getName().lastIndexOf('.')).replace(".", "/") *
+ "/" + name); * @param pathName The path name
} * @return The path reference
return url; */
} Path getLocalResource(String pathName);
public static URL getResourceRoot(String name) throws IOException {
URL url = ResourceLoader.class.getResource("/" + name);
if (url == null) {
return getResourceForgeHack(name);
}
return url;
}
} }

View File

@ -0,0 +1,38 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.io;
import com.sk89q.worldedit.WorldEdit;
import java.nio.file.Path;
public class WorldEditResourceLoader implements ResourceLoader {
private final WorldEdit worldEdit;
public WorldEditResourceLoader(WorldEdit worldEdit) {
this.worldEdit = worldEdit;
}
@Override
public Path getLocalResource(String pathName) {
return this.worldEdit.getWorkingDirectoryPath(pathName);
}
}

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.util.translation; package com.sk89q.worldedit.util.translation;
@ -23,19 +23,19 @@ import com.google.common.collect.Maps;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.renderer.FriendlyComponentRenderer; import com.sk89q.worldedit.util.formatting.text.renderer.TranslatableComponentRenderer;
import com.sk89q.worldedit.util.io.ResourceLoader; import com.sk89q.worldedit.util.io.ResourceLoader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
@ -44,36 +44,55 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
/** /**
* Handles translations for the plugin. * Handles translations for the plugin.
* *
* <p>
* These should be in the following format: * These should be in the following format:
* plugin.component.message[.meta]* * plugin.component.message[.meta]*
* </p>
* *
* <p>
* Where, * Where,
* plugin = worldedit * plugin = worldedit
* component = The part of the plugin, eg expand * component = The part of the plugin, eg expand
* message = A descriptor for which message, eg, expanded * message = A descriptor for which message, eg, expanded
* meta = Any extra information such as plural/singular (Can have none to infinite) * meta = Any extra information such as plural/singular (Can have none to infinite)
* </p>
*/ */
public class TranslationManager { public class TranslationManager {
private static final Gson gson = new GsonBuilder().create(); private static final Gson gson = new GsonBuilder().create();
private static final Type STRING_MAP_TYPE = new TypeToken<Map<String, String>>() {}.getType(); private static final Type STRING_MAP_TYPE = new TypeToken<Map<String, String>>() {}.getType();
public static String makeTranslationKey(String type, String id) {
String[] parts = id.split(":", 2);
return type + '.' + parts[0] + '.' + parts[1].replace('/', '.');
}
private final Map<Locale, Map<String, String>> translationMap = new ConcurrentHashMap<>(); private final Map<Locale, Map<String, String>> translationMap = new ConcurrentHashMap<>();
private final FriendlyComponentRenderer<Locale> friendlyComponentRenderer = FriendlyComponentRenderer.from( private final TranslatableComponentRenderer<Locale> friendlyComponentRenderer = TranslatableComponentRenderer.from(
(locale, key) -> new MessageFormat(getTranslationMap(locale).getOrDefault(key, key), locale)); (locale, key) -> {
String translation = getTranslationMap(locale).get(key);
if (translation == null) {
// let it pass through (for e.g. MC messages)
return null;
}
return new MessageFormat(translation, locale);
}
);
private Locale defaultLocale = Locale.ENGLISH; private Locale defaultLocale = Locale.ENGLISH;
private final WorldEdit worldEdit; private final ResourceLoader resourceLoader;
private final Set<Locale> checkedLocales = new HashSet<>(); private final Set<Locale> checkedLocales = new HashSet<>();
public TranslationManager(WorldEdit worldEdit) { public TranslationManager(ResourceLoader resourceLoader) {
this.worldEdit = worldEdit; checkNotNull(resourceLoader);
this.resourceLoader = resourceLoader;
} }
public void setDefaultLocale(Locale defaultLocale) { public void setDefaultLocale(Locale defaultLocale) {
@ -94,18 +113,22 @@ public class TranslationManager {
} }
private Optional<Map<String, String>> loadTranslationFile(String filename) { private Optional<Map<String, String>> loadTranslationFile(String filename) {
Map<String, String> baseTranslations; Map<String, String> baseTranslations = new ConcurrentHashMap<>();
try (InputStream stream = ResourceLoader.getResourceRoot("lang/" + filename).openStream()) { try {
baseTranslations = parseTranslationFile(stream); URL resource = resourceLoader.getRootResource("lang/" + filename);
if (resource != null) {
try (InputStream stream = resource.openStream()) {
baseTranslations = parseTranslationFile(stream);
}
}
} catch (IOException e) { } catch (IOException e) {
// Seem to be missing base. If the user has provided a file use that. // Seem to be missing base. If the user has provided a file use that.
baseTranslations = new ConcurrentHashMap<>();
} }
File localFile = worldEdit.getWorkingDirectoryFile("lang/" + filename); Path localFile = resourceLoader.getLocalResource("lang/" + filename);
if (localFile.exists()) { if (Files.exists(localFile)) {
try (InputStream stream = new FileInputStream(localFile)) { try (InputStream stream = Files.newInputStream(localFile)) {
baseTranslations.putAll(parseTranslationFile(stream)); baseTranslations.putAll(parseTranslationFile(stream));
} catch (IOException e) { } catch (IOException e) {
// Failed to parse custom language file. Worth printing. // Failed to parse custom language file. Worth printing.
@ -126,7 +149,10 @@ public class TranslationManager {
if (!locale.equals(defaultLocale)) { if (!locale.equals(defaultLocale)) {
baseTranslations.putAll(getTranslationMap(defaultLocale)); baseTranslations.putAll(getTranslationMap(defaultLocale));
} }
Optional<Map<String, String>> langData = loadTranslationFile(locale.getLanguage() + "-" + locale.getCountry() + "/strings.json"); Optional<Map<String, String>> langData = Optional.empty();
if (!locale.getCountry().isEmpty()) {
langData = loadTranslationFile(locale.getLanguage() + "-" + locale.getCountry() + "/strings.json");
}
if (!langData.isPresent()) { if (!langData.isPresent()) {
langData = loadTranslationFile(locale.getLanguage() + "/strings.json"); langData = loadTranslationFile(locale.getLanguage() + "/strings.json");
} }
@ -137,7 +163,7 @@ public class TranslationManager {
} }
if (locale.equals(defaultLocale)) { if (locale.equals(defaultLocale)) {
translationMap.put(Locale.ENGLISH, loadTranslationFile("strings.json").orElseThrow( translationMap.put(Locale.ENGLISH, loadTranslationFile("strings.json").orElseThrow(
() -> new RuntimeException("Failed to load WorldEdit strings!") () -> new RuntimeException("Failed to load WorldEdit strings!")
)); ));
return true; return true;
} }

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.world.item; package com.sk89q.worldedit.world.item;
@ -26,7 +26,9 @@ import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.registry.Keyed;
import com.sk89q.worldedit.registry.NamespacedRegistry; import com.sk89q.worldedit.registry.NamespacedRegistry;
import com.sk89q.worldedit.registry.RegistryItem; import com.sk89q.worldedit.registry.RegistryItem;
import com.sk89q.worldedit.util.GuavaUtil;
import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.registry.ItemMaterial; import com.sk89q.worldedit.world.registry.ItemMaterial;
@ -37,11 +39,24 @@ public class ItemType implements RegistryItem, Keyed {
public static final NamespacedRegistry<ItemType> REGISTRY = new NamespacedRegistry<>("item type"); public static final NamespacedRegistry<ItemType> REGISTRY = new NamespacedRegistry<>("item type");
private String id; private final String id;
private String name; @SuppressWarnings("deprecation")
private final LazyReference<ItemMaterial> itemMaterial private final LazyReference<String> name = LazyReference.from(() -> {
= LazyReference.from(() -> WorldEdit.getInstance().getPlatformManager() String name = GuavaUtil.firstNonNull(
.queryCapability(Capability.GAME_HOOKS).getRegistries().getItemRegistry().getMaterial(this)); WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
.getRegistries().getItemRegistry().getName(this),
""
);
return name.isEmpty() ? getId() : name;
});
private final LazyReference<Component> richName = LazyReference.from(() ->
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
.getRegistries().getItemRegistry().getRichName(this)
);
private final LazyReference<ItemMaterial> itemMaterial = LazyReference.from(() ->
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS)
.getRegistries().getItemRegistry().getMaterial(this)
);
private BlockType blockType; private BlockType blockType;
private boolean initBlockType; private boolean initBlockType;
private BaseItem defaultState; private BaseItem defaultState;
@ -71,20 +86,19 @@ public class ItemType implements RegistryItem, Keyed {
return internalId; return internalId;
} }
public Component getRichName() {
return richName.getValue();
}
/** /**
* Gets the name of this item, or the ID if the name cannot be found. * Gets the name of this item, or the ID if the name cannot be found.
* *
* @return The name, or ID * @return The name, or ID
* @deprecated Names are translatable now, use {@link #getRichName()}.
*/ */
@Deprecated
public String getName() { public String getName() {
if (name == null) { return name.getValue();
name = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries()
.getItemRegistry().getName(this);
if (name == null) {
name = "";
}
}
return name.isEmpty() ? getId() : name;
} }

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.world.registry; package com.sk89q.worldedit.world.registry;
@ -27,6 +27,7 @@ import com.google.gson.JsonPrimitive;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.gson.VectorAdapter; import com.sk89q.worldedit.util.gson.VectorAdapter;
import com.sk89q.worldedit.util.io.ResourceLoader; import com.sk89q.worldedit.util.io.ResourceLoader;
@ -56,6 +57,7 @@ public final class BundledBlockData {
private static final Logger log = LoggerFactory.getLogger(BundledBlockData.class); private static final Logger log = LoggerFactory.getLogger(BundledBlockData.class);
private static BundledBlockData INSTANCE; private static BundledBlockData INSTANCE;
private final ResourceLoader resourceLoader;
private final Map<String, BlockEntry> idMap = new HashMap<>(); private final Map<String, BlockEntry> idMap = new HashMap<>();
@ -63,6 +65,8 @@ public final class BundledBlockData {
* Create a new instance. * Create a new instance.
*/ */
private BundledBlockData() { private BundledBlockData() {
this.resourceLoader = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.CONFIGURATION).getResourceLoader();
try { try {
loadFromResource(); loadFromResource();
} catch (Throwable e) { } catch (Throwable e) {
@ -82,7 +86,9 @@ public final class BundledBlockData {
JsonPrimitive primitive = (JsonPrimitive) json; JsonPrimitive primitive = (JsonPrimitive) json;
if (primitive.isString()) { if (primitive.isString()) {
String value = primitive.getAsString(); String value = primitive.getAsString();
if (value.charAt(0) == '#') return Integer.parseInt(value.substring(1), 16); if (value.charAt(0) == '#') {
return Integer.parseInt(value.substring(1), 16);
}
return Integer.parseInt(value); return Integer.parseInt(value);
} }
return primitive.getAsInt(); return primitive.getAsInt();
@ -90,15 +96,15 @@ public final class BundledBlockData {
Gson gson = gsonBuilder.create(); Gson gson = gsonBuilder.create();
URL url = null; URL url = null;
final int dataVersion = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion(); final int dataVersion = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion();
if (dataVersion > 2577) { // > MC 1.15 if (dataVersion >= Constants.DATA_VERSION_MC_1_16) {
url = ResourceLoader.getResource(BundledBlockData.class, "blocks.116.json"); url = resourceLoader.getResource(BundledBlockData.class, "blocks.116.json");
} else if (dataVersion > 2224) { // > MC 1.14 } else if (dataVersion >= Constants.DATA_VERSION_MC_1_15) {
url = ResourceLoader.getResource(BundledBlockData.class, "blocks.115.json"); url = resourceLoader.getResource(BundledBlockData.class, "blocks.115.json");
} else if (dataVersion > 1900) { // > MC 1.13 } else if (dataVersion >= Constants.DATA_VERSION_MC_1_14) {
url = ResourceLoader.getResource(BundledBlockData.class, "blocks.114.json"); url = resourceLoader.getResource(BundledBlockData.class, "blocks.114.json");
} }
if (url == null) { if (url == null) {
url = ResourceLoader.getResource(BundledBlockData.class, "blocks.json"); url = resourceLoader.getResource(BundledBlockData.class, "blocks.json");
} }
if (url == null) { if (url == null) {
throw new IOException("Could not find blocks.json"); throw new IOException("Could not find blocks.json");

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.world.registry; package com.sk89q.worldedit.world.registry;
@ -25,6 +25,7 @@ import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.gson.VectorAdapter; import com.sk89q.worldedit.util.gson.VectorAdapter;
import com.sk89q.worldedit.util.io.ResourceLoader; import com.sk89q.worldedit.util.io.ResourceLoader;
@ -54,6 +55,7 @@ public final class BundledItemData {
private static final Logger log = LoggerFactory.getLogger(BundledItemData.class); private static final Logger log = LoggerFactory.getLogger(BundledItemData.class);
private static BundledItemData INSTANCE; private static BundledItemData INSTANCE;
private final ResourceLoader resourceLoader;
private final Map<String, ItemEntry> idMap = new HashMap<>(); private final Map<String, ItemEntry> idMap = new HashMap<>();
@ -61,6 +63,8 @@ public final class BundledItemData {
* Create a new instance. * Create a new instance.
*/ */
private BundledItemData() { private BundledItemData() {
this.resourceLoader = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.CONFIGURATION).getResourceLoader();
try { try {
loadFromResource(); loadFromResource();
} catch (Throwable e) { } catch (Throwable e) {
@ -79,15 +83,15 @@ public final class BundledItemData {
Gson gson = gsonBuilder.create(); Gson gson = gsonBuilder.create();
URL url = null; URL url = null;
final int dataVersion = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion(); final int dataVersion = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion();
if (dataVersion > 2577) { // > MC 1.15 if (dataVersion >= Constants.DATA_VERSION_MC_1_16) {
url = ResourceLoader.getResource(BundledBlockData.class, "items.116.json"); url = resourceLoader.getResource(BundledBlockData.class, "items.116.json");
} else if (dataVersion > 2224) { // > MC 1.14 } else if (dataVersion >= Constants.DATA_VERSION_MC_1_15) {
url = ResourceLoader.getResource(BundledBlockData.class, "items.115.json"); url = resourceLoader.getResource(BundledBlockData.class, "items.115.json");
} else if (dataVersion > 1900) { // > MC 1.13 } else if (dataVersion >= Constants.DATA_VERSION_MC_1_14) {
url = ResourceLoader.getResource(BundledBlockData.class, "items.114.json"); url = resourceLoader.getResource(BundledBlockData.class, "items.114.json");
} }
if (url == null) { if (url == null) {
url = ResourceLoader.getResource(BundledBlockData.class, "items.json"); url = resourceLoader.getResource(BundledBlockData.class, "items.json");
} }
if (url == null) { if (url == null) {
throw new IOException("Could not find items.json"); throw new IOException("Could not find items.json");

View File

@ -3,22 +3,26 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.world.registry; package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.util.translation.TranslationManager;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -33,8 +37,26 @@ public class BundledItemRegistry implements ItemRegistry {
return BundledItemData.getInstance().findById(itemType.getId()); return BundledItemData.getInstance().findById(itemType.getId());
} }
@Override
public Component getRichName(ItemType itemType) {
BundledItemData.ItemEntry itemEntry = getEntryById(itemType);
if (itemEntry != null && !itemEntry.localizedName.equals("Air")) {
// This is more likely to be "right", but not translated
// Some vanilla MC items have overrides so we need this name here
// Most platforms should be overriding this anyways, so it likely doesn't matter
// too much!
return TextComponent.of(itemEntry.localizedName);
}
return TranslatableComponent.of(
TranslationManager.makeTranslationKey("item", itemType.getId())
);
}
@Nullable @Nullable
@Override @Override
@Deprecated
// dumb_intellij.jpg
@SuppressWarnings("deprecation")
public String getName(ItemType itemType) { public String getName(ItemType itemType) {
BundledItemData.ItemEntry itemEntry = getEntryById(itemType); BundledItemData.ItemEntry itemEntry = getEntryById(itemType);
if (itemEntry != null) { if (itemEntry != null) {

View File

@ -3,22 +3,24 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.world.registry; package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import java.util.Collection; import java.util.Collection;
@ -27,15 +29,36 @@ import javax.annotation.Nullable;
public interface ItemRegistry { public interface ItemRegistry {
/**
* Gets the name for the given item.
*
* @param itemType the item
* @return The name
*/
Component getRichName(ItemType itemType);
/**
* Gets the name for the given item stack.
*
* @param itemStack the item stack
* @return The name
*/
default Component getRichName(BaseItemStack itemStack) {
return getRichName(itemStack.getType());
}
/** /**
* Gets the name for the given item. * Gets the name for the given item.
* *
* @param itemType the item * @param itemType the item
* @return The name, or null if it's unknown * @return The name, or null if it's unknown
* @deprecated Names are now translatable, use {@link #getRichName(ItemType)}.
*/ */
@Deprecated @Deprecated
@Nullable @Nullable
String getName(ItemType itemType); default String getName(ItemType itemType) {
return getRichName(itemType).toString();
}
/** /**
* Get the material for the given item. * Get the material for the given item.
@ -47,7 +70,7 @@ public interface ItemRegistry {
ItemMaterial getMaterial(ItemType itemType); ItemMaterial getMaterial(ItemType itemType);
/** /**
* Register all items * Register all items.
*/ */
default Collection<String> values() { default Collection<String> values() {
return Collections.emptyList(); return Collections.emptyList();

View File

@ -3,18 +3,18 @@
* Copyright (C) sk89q <http://www.sk89q.com> * Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors * Copyright (C) WorldEdit team and contributors
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Lesser General Public License as published by the * it under the terms of the GNU General Public License as published by
* Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful,
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * but WITHOUT ANY WARRANTY; without even the implied warranty of
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.world.registry; package com.sk89q.worldedit.world.registry;
@ -32,6 +32,7 @@ import com.sk89q.worldedit.extension.factory.BlockFactory;
import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.util.gson.VectorAdapter; import com.sk89q.worldedit.util.gson.VectorAdapter;
@ -57,21 +58,24 @@ public final class LegacyMapper {
private static final Logger log = LoggerFactory.getLogger(LegacyMapper.class); private static final Logger log = LoggerFactory.getLogger(LegacyMapper.class);
private static LegacyMapper INSTANCE; private static LegacyMapper INSTANCE;
private final ResourceLoader resourceLoader;
private final Int2ObjectArrayMap<Integer> blockStateToLegacyId4Data = new Int2ObjectArrayMap<>(); private final Int2ObjectArrayMap<Integer> blockStateToLegacyId4Data = new Int2ObjectArrayMap<>();
private final Int2ObjectArrayMap<Integer> extraId4DataToStateId = new Int2ObjectArrayMap<>(); private final Int2ObjectArrayMap<Integer> extraId4DataToStateId = new Int2ObjectArrayMap<>();
private final int[] blockArr = new int[4096]; private final int[] blockArr = new int[4096];
private final BiMap<Integer, ItemType> itemMap = HashBiMap.create(); private final BiMap<Integer, ItemType> itemMap = HashBiMap.create();
private Map<String, String> blockEntries = new HashMap<>(); private Map<String, String> blockEntries = new HashMap<>();
private Map<String, BlockState> stringToBlockMap = new HashMap<>(); private final Map<String, BlockState> stringToBlockMap = new HashMap<>();
private Multimap<BlockState, String> blockToStringMap = HashMultimap.create(); private final Multimap<BlockState, String> blockToStringMap = HashMultimap.create();
private Map<String, ItemType> stringToItemMap = new HashMap<>(); private final Map<String, ItemType> stringToItemMap = new HashMap<>();
private Multimap<ItemType, String> itemToStringMap = HashMultimap.create(); private final Multimap<ItemType, String> itemToStringMap = HashMultimap.create();
/** /**
* Create a new instance. * Create a new instance.
*/ */
private LegacyMapper() { private LegacyMapper() {
this.resourceLoader = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.CONFIGURATION).getResourceLoader();
try { try {
loadFromResource(); loadFromResource();
} catch (Throwable e) { } catch (Throwable e) {
@ -88,7 +92,7 @@ public final class LegacyMapper {
GsonBuilder gsonBuilder = new GsonBuilder(); GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Vector3.class, new VectorAdapter()); gsonBuilder.registerTypeAdapter(Vector3.class, new VectorAdapter());
Gson gson = gsonBuilder.disableHtmlEscaping().create(); Gson gson = gsonBuilder.disableHtmlEscaping().create();
URL url = ResourceLoader.getResource(LegacyMapper.class, "legacy.json"); URL url = resourceLoader.getResource(LegacyMapper.class, "legacy.json");
if (url == null) { if (url == null) {
throw new IOException("Could not find legacy.json"); throw new IOException("Could not find legacy.json");
} }
@ -122,7 +126,7 @@ public final class LegacyMapper {
try { try {
String newEntry = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, value, 1631); String newEntry = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, value, 1631);
state = blockFactory.parseFromInput(newEntry, parserContext).toImmutableState(); state = blockFactory.parseFromInput(newEntry, parserContext).toImmutableState();
} catch (InputParseException e) { } catch (InputParseException ignored) {
} }
} }
@ -130,7 +134,7 @@ public final class LegacyMapper {
if (state == null) { if (state == null) {
try { try {
state = blockFactory.parseFromInput(value, parserContext).toImmutableState(); state = blockFactory.parseFromInput(value, parserContext).toImmutableState();
} catch (InputParseException e) { } catch (InputParseException ignored) {
} }
} }
@ -164,7 +168,7 @@ public final class LegacyMapper {
String value = itemEntry.getValue(); String value = itemEntry.getValue();
ItemType type = ItemTypes.get(value); ItemType type = ItemTypes.get(value);
if (type == null && fixer != null) { if (type == null && fixer != null) {
value = fixer.fixUp(DataFixer.FixTypes.ITEM_TYPE, value, 1631); value = fixer.fixUp(DataFixer.FixTypes.ITEM_TYPE, value, Constants.DATA_VERSION_MC_1_13_2);
type = ItemTypes.get(value); type = ItemTypes.get(value);
} }
if (type == null) { if (type == null) {