mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Allow for implementations to provide a custom resource loader
This will allow Geyser-Fabric to work without resource loading issues. This commit also ensures try-with-resources is used anywhere a resource is accessed.
This commit is contained in:
parent
9084c59003
commit
763743a845
22 changed files with 220 additions and 211 deletions
|
@ -63,17 +63,21 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
if (!getDataFolder().exists())
|
||||
getDataFolder().mkdir();
|
||||
|
||||
try {
|
||||
if (!getDataFolder().exists())
|
||||
getDataFolder().mkdir();
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"),
|
||||
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.WARNING, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
if (getProxy().getConfig().getListeners().size() == 1) {
|
||||
|
|
|
@ -79,16 +79,21 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
// This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed
|
||||
try {
|
||||
if (!getDataFolder().exists()) {
|
||||
getDataFolder().mkdir();
|
||||
}
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml",
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
getLogger().log(Level.WARNING, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -71,15 +71,19 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
|
|||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
if (!configDir.exists())
|
||||
configDir.mkdirs();
|
||||
|
||||
File configFile = null;
|
||||
File configFile;
|
||||
try {
|
||||
configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml",
|
||||
(file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
} catch (IOException ex) {
|
||||
logger.warn(GeyserLocale.getLocaleStringLog("geyser.config.failed"));
|
||||
logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"));
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -90,6 +90,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
boolean useGuiOpts = bootstrap.useGui;
|
||||
String configFilenameOpt = bootstrap.configFilename;
|
||||
|
||||
GeyserLocale.init(bootstrap);
|
||||
|
||||
List<BeanPropertyDefinition> availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
|
@ -188,7 +190,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
LoopbackUtil.checkLoopback(geyserLogger);
|
||||
|
||||
try {
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml",
|
||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
|
||||
|
||||
handleArgsConfigOptions();
|
||||
|
|
|
@ -83,16 +83,19 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
try {
|
||||
if (!configFolder.toFile().exists())
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
configFolder.toFile().mkdirs();
|
||||
File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(),
|
||||
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
|
||||
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
logger.warn(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
InetSocketAddress javaAddr = proxyServer.getBoundAddress();
|
||||
|
|
|
@ -25,16 +25,16 @@
|
|||
|
||||
package org.geysermc.geyser;
|
||||
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.level.GeyserWorldManager;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.InputStream;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
@ -126,4 +126,29 @@ public interface GeyserBootstrap {
|
|||
default Path getLogsPath() {
|
||||
return Paths.get("logs/latest.log");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an InputStream for the given resource path.
|
||||
* Overridden on platforms that have different class loader properties.
|
||||
*
|
||||
* @param resource Resource to get
|
||||
* @return InputStream of the given resource, or null if not found
|
||||
*/
|
||||
default @Nullable InputStream getResourceOrNull(String resource) {
|
||||
return GeyserBootstrap.class.getClassLoader().getResourceAsStream(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an InputStream for the given resource path, throws AssertionError if resource is not found.
|
||||
*
|
||||
* @param resource Resource to get
|
||||
* @return InputStream of the given resource
|
||||
*/
|
||||
default @Nonnull InputStream getResource(String resource) {
|
||||
InputStream stream = getResourceOrNull(resource);
|
||||
if (stream == null) {
|
||||
throw new AssertionError("Unable to find resource: " + resource);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ import org.geysermc.geyser.util.*;
|
|||
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -139,6 +140,8 @@ public class GeyserImpl implements GeyserApi {
|
|||
|
||||
this.platformType = platformType;
|
||||
|
||||
GeyserLocale.finalizeDefaultLocale(this);
|
||||
|
||||
logger.info("******************************************");
|
||||
logger.info("");
|
||||
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.load", NAME, VERSION));
|
||||
|
@ -214,9 +217,9 @@ public class GeyserImpl implements GeyserApi {
|
|||
String branch = "unknown";
|
||||
int buildNumber = -1;
|
||||
if (this.productionEnvironment()) {
|
||||
try {
|
||||
try (InputStream stream = bootstrap.getResource("git.properties")) {
|
||||
Properties gitProperties = new Properties();
|
||||
gitProperties.load(FileUtils.getResource("git.properties"));
|
||||
gitProperties.load(stream);
|
||||
branch = gitProperties.getProperty("git.branch");
|
||||
String build = gitProperties.getProperty("git.build.number");
|
||||
if (build != null) {
|
||||
|
|
|
@ -30,14 +30,14 @@ import org.geysermc.common.PlatformType;
|
|||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.WebUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
@ -69,9 +69,9 @@ public class VersionCommand extends GeyserCommand {
|
|||
// Disable update checking in dev mode and for players in Geyser Standalone
|
||||
if (GeyserImpl.getInstance().productionEnvironment() && !(!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) {
|
||||
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", sender.getLocale()));
|
||||
try {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("git.properties")) {
|
||||
Properties gitProp = new Properties();
|
||||
gitProp.load(FileUtils.getResource("git.properties"));
|
||||
gitProp.load(stream);
|
||||
|
||||
String buildXML = WebUtils.getBody("https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/" +
|
||||
URLEncoder.encode(gitProp.getProperty("git.branch"), StandardCharsets.UTF_8.toString()) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber");
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.geysermc.floodgate.util.FloodgateInfoHolder;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
@ -78,9 +79,9 @@ public class DumpInfo {
|
|||
public DumpInfo(boolean addLog) {
|
||||
this.versionInfo = new VersionInfo();
|
||||
|
||||
try {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("git.properties")) {
|
||||
this.gitInfo = new Properties();
|
||||
this.gitInfo.load(FileUtils.getResource("git.properties"));
|
||||
this.gitInfo.load(stream);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -45,10 +44,10 @@ public class BiomeIdentifierRegistryLoader implements RegistryLoader<String, Obj
|
|||
// The server sends the corresponding Java network IDs, so we don't need to worry about that now.
|
||||
|
||||
// Reference variable for Jackson to read off of
|
||||
TypeReference<Map<String, BiomeEntry>> biomeEntriesType = new TypeReference<Map<String, BiomeEntry>>() { };
|
||||
TypeReference<Map<String, BiomeEntry>> biomeEntriesType = new TypeReference<>() { };
|
||||
Map<String, BiomeEntry> biomeEntries;
|
||||
|
||||
try (InputStream stream = FileUtils.getResource("mappings/biomes.json")) {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/biomes.json")) {
|
||||
biomeEntries = GeyserImpl.JSON_MAPPER.readValue(stream, biomeEntriesType);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("Unable to load Bedrock runtime biomes", e);
|
||||
|
|
|
@ -65,10 +65,8 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
|||
}
|
||||
|
||||
// Load collision mappings file
|
||||
InputStream stream = FileUtils.getResource(input.value());
|
||||
|
||||
List<BoundingBox[]> collisionList;
|
||||
try {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(input.value())) {
|
||||
ArrayNode collisionNode = (ArrayNode) GeyserImpl.JSON_MAPPER.readTree(stream);
|
||||
collisionList = loadBoundingBoxes(collisionNode);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.registry.loader;
|
|||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
@ -43,10 +42,9 @@ public abstract class EffectRegistryLoader<T> implements RegistryLoader<String,
|
|||
|
||||
public void loadFile(String input) {
|
||||
if (!loadedFiles.containsKey(input)) {
|
||||
InputStream effectsStream = FileUtils.getResource(input);
|
||||
JsonNode effects;
|
||||
try {
|
||||
effects = GeyserImpl.JSON_MAPPER.readTree(effectsStream);
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(input)) {
|
||||
effects = GeyserImpl.JSON_MAPPER.readTree(stream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load registrations for " + input, e);
|
||||
}
|
||||
|
|
|
@ -29,12 +29,11 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.EnchantmentData;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.EnumMap;
|
||||
|
@ -45,9 +44,8 @@ import java.util.Map;
|
|||
public class EnchantmentRegistryLoader implements RegistryLoader<String, Map<JavaEnchantment, EnchantmentData>> {
|
||||
@Override
|
||||
public Map<JavaEnchantment, EnchantmentData> load(String input) {
|
||||
InputStream enchantmentsStream = FileUtils.getResource(input);
|
||||
JsonNode enchantmentsNode;
|
||||
try {
|
||||
try (InputStream enchantmentsStream = GeyserImpl.getInstance().getBootstrap().getResource(input)) {
|
||||
enchantmentsNode = GeyserImpl.JSON_MAPPER.readTree(enchantmentsStream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load enchantment data", e);
|
||||
|
|
|
@ -28,9 +28,7 @@ package org.geysermc.geyser.registry.loader;
|
|||
import com.nukkitx.nbt.NBTInputStream;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtUtils;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
|
||||
/**
|
||||
* Loads NBT data from the given resource path.
|
||||
|
@ -39,8 +37,8 @@ public class NbtRegistryLoader implements RegistryLoader<String, NbtMap> {
|
|||
|
||||
@Override
|
||||
public NbtMap load(String input) {
|
||||
InputStream stream = FileUtils.getResource(input);
|
||||
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream, true, true)) {
|
||||
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(GeyserImpl.getInstance().getBootstrap().getResource(input),
|
||||
true, true)) {
|
||||
return (NbtMap) nbtInputStream.readTag();
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Failed to load registrations for " + input, e);
|
||||
|
|
|
@ -28,7 +28,6 @@ package org.geysermc.geyser.registry.loader;
|
|||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.registry.type.SoundMapping;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -43,9 +42,8 @@ public class SoundRegistryLoader implements RegistryLoader<String, Map<String, S
|
|||
|
||||
@Override
|
||||
public Map<String, SoundMapping> load(String input) {
|
||||
InputStream stream = FileUtils.getResource(input);
|
||||
JsonNode soundsTree;
|
||||
try {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(input)) {
|
||||
soundsTree = GeyserImpl.JSON_MAPPER.readTree(stream);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("Unable to load sound mappings", e);
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.geysermc.geyser.registry.BlockRegistries;
|
|||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
import org.geysermc.geyser.registry.type.BlockMappings;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.InputStream;
|
||||
|
@ -83,9 +82,9 @@ public class BlockRegistryPopulator {
|
|||
|
||||
private static void registerBedrockBlocks() {
|
||||
for (Map.Entry<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> palette : BLOCK_MAPPERS.entrySet()) {
|
||||
InputStream stream = FileUtils.getResource(String.format("bedrock/block_palette.%s.nbt", palette.getKey().key()));
|
||||
NbtList<NbtMap> blocksTag;
|
||||
try (NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(String.format("bedrock/block_palette.%s.nbt", palette.getKey().key()));
|
||||
NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) {
|
||||
NbtMap blockPalette = (NbtMap) nbtInputStream.readTag();
|
||||
blocksTag = (NbtList<NbtMap>) blockPalette.getList("blocks", NbtType.COMPOUND);
|
||||
} catch (Exception e) {
|
||||
|
@ -208,10 +207,8 @@ public class BlockRegistryPopulator {
|
|||
}
|
||||
|
||||
private static void registerJavaBlocks() {
|
||||
InputStream stream = FileUtils.getResource("mappings/blocks.json");
|
||||
|
||||
JsonNode blocksJson;
|
||||
try {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/blocks.json")) {
|
||||
blocksJson = GeyserImpl.JSON_MAPPER.readTree(stream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load Java block mappings", e);
|
||||
|
|
|
@ -38,14 +38,17 @@ import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
|||
import com.nukkitx.protocol.bedrock.v465.Bedrock_v465;
|
||||
import com.nukkitx.protocol.bedrock.v471.Bedrock_v471;
|
||||
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.item.StoredItemMappings;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.*;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -69,13 +72,13 @@ public class ItemRegistryPopulator {
|
|||
}
|
||||
|
||||
public static void populate() {
|
||||
// Load item mappings from Java Edition to Bedrock Edition
|
||||
InputStream stream = FileUtils.getResource("mappings/items.json");
|
||||
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
|
||||
|
||||
TypeReference<Map<String, GeyserMappingItem>> mappingItemsType = new TypeReference<>() { };
|
||||
|
||||
Map<String, GeyserMappingItem> items;
|
||||
try {
|
||||
try (InputStream stream = bootstrap.getResource("mappings/items.json")) {
|
||||
// Load item mappings from Java Edition to Bedrock Edition
|
||||
items = GeyserImpl.JSON_MAPPER.readValue(stream, mappingItemsType);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load Java runtime item IDs", e);
|
||||
|
@ -83,8 +86,6 @@ public class ItemRegistryPopulator {
|
|||
|
||||
/* Load item palette */
|
||||
for (Map.Entry<String, PaletteVersion> palette : PALETTE_VERSIONS.entrySet()) {
|
||||
stream = FileUtils.getResource(String.format("bedrock/runtime_item_states.%s.json", palette.getKey()));
|
||||
|
||||
TypeReference<List<PaletteItem>> paletteEntriesType = new TypeReference<>() {};
|
||||
|
||||
// Used to get the Bedrock namespaced ID (in instances where there are small differences)
|
||||
|
@ -94,7 +95,7 @@ public class ItemRegistryPopulator {
|
|||
List<String> itemNames = new ArrayList<>();
|
||||
|
||||
List<PaletteItem> itemEntries;
|
||||
try {
|
||||
try (InputStream stream = bootstrap.getResource(String.format("bedrock/runtime_item_states.%s.json", palette.getKey()))) {
|
||||
itemEntries = GeyserImpl.JSON_MAPPER.readValue(stream, paletteEntriesType);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load Bedrock runtime item IDs", e);
|
||||
|
@ -112,10 +113,8 @@ public class ItemRegistryPopulator {
|
|||
|
||||
// Load creative items
|
||||
// We load this before item mappings to get overridden block runtime ID mappings
|
||||
stream = FileUtils.getResource(String.format("bedrock/creative_items.%s.json", palette.getKey()));
|
||||
|
||||
JsonNode creativeItemEntries;
|
||||
try {
|
||||
try (InputStream stream = bootstrap.getResource(String.format("bedrock/creative_items.%s.json", palette.getKey()))) {
|
||||
creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("items");
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load creative items", e);
|
||||
|
|
|
@ -40,12 +40,11 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -60,10 +59,8 @@ import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID;
|
|||
public class RecipeRegistryPopulator {
|
||||
|
||||
public static void populate() {
|
||||
InputStream stream = FileUtils.getResource("mappings/recipes.json");
|
||||
|
||||
JsonNode items;
|
||||
try {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/recipes.json")) {
|
||||
items = GeyserImpl.JSON_MAPPER.readTree(stream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e);
|
||||
|
|
|
@ -26,21 +26,25 @@
|
|||
package org.geysermc.geyser.skin;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ProvidedSkin {
|
||||
@Getter private byte[] skin;
|
||||
|
||||
public ProvidedSkin(String internalUrl) {
|
||||
try {
|
||||
BufferedImage image = ImageIO.read(ProvidedSkin.class.getClassLoader().getResource(internalUrl));
|
||||
BufferedImage image;
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(internalUrl)) {
|
||||
image = ImageIO.read(stream);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(image.getWidth() * 4 + image.getHeight() * 4);
|
||||
try {
|
||||
for (int y = 0; y < image.getHeight(); y++) {
|
||||
for (int x = 0; x < image.getWidth(); x++) {
|
||||
int rgba = image.getRGB(x, y);
|
||||
|
@ -52,11 +56,6 @@ public class ProvidedSkin {
|
|||
}
|
||||
image.flush();
|
||||
skin = outputStream.toByteArray();
|
||||
} finally {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -94,19 +94,19 @@ public class SkinProvider {
|
|||
|
||||
static {
|
||||
/* Load in the normal ears geometry */
|
||||
EARS_GEOMETRY = new String(FileUtils.readAllBytes(FileUtils.getResource("bedrock/skin/geometry.humanoid.ears.json")), StandardCharsets.UTF_8);
|
||||
EARS_GEOMETRY = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.ears.json"), StandardCharsets.UTF_8);
|
||||
|
||||
/* Load in the slim ears geometry */
|
||||
EARS_GEOMETRY_SLIM = new String(FileUtils.readAllBytes(FileUtils.getResource("bedrock/skin/geometry.humanoid.earsSlim.json")), StandardCharsets.UTF_8);
|
||||
EARS_GEOMETRY_SLIM = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.earsSlim.json"), StandardCharsets.UTF_8);
|
||||
|
||||
/* Load in the custom skull geometry */
|
||||
String skullData = new String(FileUtils.readAllBytes(FileUtils.getResource("bedrock/skin/geometry.humanoid.customskull.json")), StandardCharsets.UTF_8);
|
||||
String skullData = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.customskull.json"), StandardCharsets.UTF_8);
|
||||
SKULL_GEOMETRY = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.customskull\"}}", skullData, false);
|
||||
|
||||
/* Load in the player head skull geometry */
|
||||
String wearingCustomSkull = new String(FileUtils.readAllBytes(FileUtils.getResource("bedrock/skin/geometry.humanoid.wearingCustomSkull.json")), StandardCharsets.UTF_8);
|
||||
String wearingCustomSkull = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.wearingCustomSkull.json"), StandardCharsets.UTF_8);
|
||||
WEARING_CUSTOM_SKULL = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkull\"}}", wearingCustomSkull, false);
|
||||
String wearingCustomSkullSlim = new String(FileUtils.readAllBytes(FileUtils.getResource("bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json")), StandardCharsets.UTF_8);
|
||||
String wearingCustomSkullSlim = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json"), StandardCharsets.UTF_8);
|
||||
WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim, false);
|
||||
|
||||
// Schedule Daily Image Expiry if we are caching them
|
||||
|
|
|
@ -25,9 +25,10 @@
|
|||
|
||||
package org.geysermc.geyser.text;
|
||||
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -40,17 +41,59 @@ import java.util.Properties;
|
|||
public class GeyserLocale {
|
||||
|
||||
/**
|
||||
* If we determine the locale that the user wishes to use, use that locale
|
||||
* If we determine the default locale that the user wishes to use, use that locale
|
||||
*/
|
||||
private static String CACHED_LOCALE;
|
||||
private static String DEFAULT_LOCALE;
|
||||
/**
|
||||
* Whether the system locale cannot be loaded by Geyser.
|
||||
*/
|
||||
private static boolean SYSTEM_LOCALE_INVALID;
|
||||
|
||||
private static final Map<String, Properties> LOCALE_MAPPINGS = new HashMap<>();
|
||||
|
||||
static {
|
||||
// Load it as a backup in case something goes really wrong
|
||||
if (!"en_US".equals(formatLocale(getDefaultLocale()))) { // getDefaultLocale() loads the locale automatically
|
||||
loadGeyserLocale("en_US");
|
||||
/**
|
||||
* Loads the initial locale(s) with the help of the bootstrap.
|
||||
*/
|
||||
public static void init(GeyserBootstrap bootstrap) {
|
||||
String defaultLocale = formatLocale(Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry());
|
||||
String loadedLocale = loadGeyserLocale(defaultLocale, bootstrap);
|
||||
if (loadedLocale != null) {
|
||||
DEFAULT_LOCALE = loadedLocale;
|
||||
// Load English as a backup in case something goes really wrong
|
||||
if (!"en_US".equals(loadedLocale)) {
|
||||
loadGeyserLocale("en_US", bootstrap);
|
||||
}
|
||||
SYSTEM_LOCALE_INVALID = false;
|
||||
} else {
|
||||
DEFAULT_LOCALE = loadGeyserLocale("en_US", bootstrap);
|
||||
if (DEFAULT_LOCALE == null) {
|
||||
// en_US can't be loaded?
|
||||
throw new IllegalStateException("English locale not found in Geyser. Did you clone the submodules? (git submodule update --init)");
|
||||
}
|
||||
SYSTEM_LOCALE_INVALID = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize the default locale, now that we know what the default locale should be.
|
||||
*/
|
||||
public static void finalizeDefaultLocale(GeyserImpl geyser) {
|
||||
String newDefaultLocale = geyser.getConfig().getDefaultLocale();
|
||||
if (newDefaultLocale == null) {
|
||||
// We want to use the system locale which is already loaded
|
||||
return;
|
||||
}
|
||||
String loadedNewLocale = loadGeyserLocale(newDefaultLocale, geyser.getBootstrap());
|
||||
if (loadedNewLocale != null) {
|
||||
// The config's locale is valid
|
||||
DEFAULT_LOCALE = loadedNewLocale;
|
||||
} else if (SYSTEM_LOCALE_INVALID) {
|
||||
geyser.getLogger().warning(Locale.getDefault().toString() + " is not a valid Bedrock language.");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDefaultLocale() {
|
||||
return DEFAULT_LOCALE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,16 +102,25 @@ public class GeyserLocale {
|
|||
* @param locale Locale to load
|
||||
*/
|
||||
public static void loadGeyserLocale(String locale) {
|
||||
GeyserImpl geyser = GeyserImpl.getInstance();
|
||||
if (geyser == null) {
|
||||
throw new IllegalStateException("Geyser instance cannot be null when loading a locale!");
|
||||
}
|
||||
loadGeyserLocale(locale, geyser.getBootstrap());
|
||||
}
|
||||
|
||||
private static String loadGeyserLocale(String locale, GeyserBootstrap bootstrap) {
|
||||
locale = formatLocale(locale);
|
||||
// Don't load the locale if it's already loaded.
|
||||
if (LOCALE_MAPPINGS.containsKey(locale)) {
|
||||
return;
|
||||
return locale;
|
||||
}
|
||||
|
||||
InputStream localeStream = GeyserImpl.class.getClassLoader().getResourceAsStream("languages/texts/" + locale + ".properties");
|
||||
InputStream localeStream = bootstrap.getResourceOrNull("languages/texts/" + locale + ".properties");
|
||||
|
||||
// Load the locale
|
||||
if (localeStream != null) {
|
||||
try {
|
||||
Properties localeProp = new Properties();
|
||||
try (InputStreamReader reader = new InputStreamReader(localeStream, StandardCharsets.UTF_8)) {
|
||||
localeProp.load(reader);
|
||||
|
@ -78,10 +130,17 @@ public class GeyserLocale {
|
|||
|
||||
// Insert the locale into the mappings
|
||||
LOCALE_MAPPINGS.put(locale, localeProp);
|
||||
return locale;
|
||||
} finally {
|
||||
try {
|
||||
localeStream.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
} else {
|
||||
if (GeyserImpl.getInstance() != null && GeyserImpl.getInstance().getLogger() != null) {
|
||||
if (GeyserImpl.getInstance() != null) {
|
||||
GeyserImpl.getInstance().getLogger().warning("Missing locale: " + locale);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,66 +216,4 @@ public class GeyserLocale {
|
|||
String country = locale.substring(3);
|
||||
return language.toLowerCase(Locale.ENGLISH) + "_" + country.toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default locale that Geyser should use
|
||||
* @return the current default locale
|
||||
*/
|
||||
public static String getDefaultLocale() {
|
||||
if (CACHED_LOCALE != null) {
|
||||
return CACHED_LOCALE; // We definitely know the locale the user is using
|
||||
}
|
||||
|
||||
String locale;
|
||||
boolean isValid = true;
|
||||
if (GeyserImpl.getInstance() != null &&
|
||||
GeyserImpl.getInstance().getConfig() != null &&
|
||||
GeyserImpl.getInstance().getConfig().getDefaultLocale() != null) { // If the config option for getDefaultLocale does not equal null, use that
|
||||
locale = formatLocale(GeyserImpl.getInstance().getConfig().getDefaultLocale());
|
||||
if (isValidLanguage(locale)) {
|
||||
CACHED_LOCALE = locale;
|
||||
return locale;
|
||||
} else {
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
locale = formatLocale(Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry());
|
||||
if (!isValidLanguage(locale)) { // Bedrock does not support this language
|
||||
locale = "en_US";
|
||||
loadGeyserLocale(locale);
|
||||
}
|
||||
if (GeyserImpl.getInstance() != null &&
|
||||
GeyserImpl.getInstance().getConfig() != null && (GeyserImpl.getInstance().getConfig().getDefaultLocale() == null || !isValid)) { // Means we should use the system locale for sure
|
||||
CACHED_LOCALE = locale;
|
||||
}
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the given locale is supported by Bedrock
|
||||
* @param locale the locale to validate
|
||||
* @return true if the given locale is supported by Bedrock and by extension Geyser
|
||||
*/
|
||||
private static boolean isValidLanguage(String locale) {
|
||||
boolean result = true;
|
||||
if (FileUtils.class.getResource("/languages/texts/" + locale + ".properties") == null) {
|
||||
result = false;
|
||||
if (GeyserImpl.getInstance() != null && GeyserImpl.getInstance().getLogger() != null) { // Could be too early for these to be initialized
|
||||
if (locale.equals("en_US")) {
|
||||
GeyserImpl.getInstance().getLogger().error("English locale not found in Geyser. Did you clone the submodules? (git submodule update --init)");
|
||||
} else {
|
||||
GeyserImpl.getInstance().getLogger().warning(locale + " is not a valid Bedrock language."); // We can't translate this since we just loaded an invalid language
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!LOCALE_MAPPINGS.containsKey(locale)) {
|
||||
loadGeyserLocale(locale);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,9 @@
|
|||
|
||||
package org.geysermc.geyser.util;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -58,28 +57,11 @@ public class FileUtils {
|
|||
return objectMapper.readValue(src, valueType);
|
||||
}
|
||||
|
||||
public static <T> T loadYaml(InputStream src, Class<T> valueType) throws IOException {
|
||||
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()).enable(JsonParser.Feature.IGNORE_UNDEFINED).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
return objectMapper.readValue(src, valueType);
|
||||
}
|
||||
|
||||
public static <T> T loadJson(InputStream src, Class<T> valueType) throws IOException {
|
||||
// Read specifically with UTF-8 to allow any non-UTF-encoded JSON to read
|
||||
return GeyserImpl.JSON_MAPPER.readValue(new InputStreamReader(src, StandardCharsets.UTF_8), valueType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the specified file or copy if from resources
|
||||
*
|
||||
* @param name File and resource name
|
||||
* @param fallback Formatting callback
|
||||
* @return File handle of the specified file
|
||||
* @throws IOException if the file failed to copy from resource
|
||||
*/
|
||||
public static File fileOrCopiedFromResource(String name, Function<String, String> fallback) throws IOException {
|
||||
return fileOrCopiedFromResource(new File(name), name, fallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the specified file or copy if from resources
|
||||
*
|
||||
|
@ -89,12 +71,12 @@ public class FileUtils {
|
|||
* @return File handle of the specified file
|
||||
* @throws IOException if the file failed to copy from resource
|
||||
*/
|
||||
public static File fileOrCopiedFromResource(File file, String name, Function<String, String> format) throws IOException {
|
||||
public static File fileOrCopiedFromResource(File file, String name, Function<String, String> format, GeyserBootstrap bootstrap) throws IOException {
|
||||
if (!file.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
file.createNewFile();
|
||||
try (FileOutputStream fos = new FileOutputStream(file)) {
|
||||
try (InputStream input = GeyserImpl.class.getResourceAsStream("/" + name)) { // resources need leading "/" prefix
|
||||
try (InputStream input = bootstrap.getResource(name)) {
|
||||
byte[] bytes = new byte[input.available()];
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
|
@ -144,20 +126,6 @@ public class FileUtils {
|
|||
writeFile(new File(name), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an InputStream for the given resource path, throws AssertionError if resource is not found
|
||||
*
|
||||
* @param resource Resource to get
|
||||
* @return InputStream of the given resource
|
||||
*/
|
||||
public static InputStream getResource(String resource) {
|
||||
InputStream stream = FileUtils.class.getClassLoader().getResourceAsStream(resource);
|
||||
if (stream == null) {
|
||||
throw new AssertionError("Unable to find resource: " + resource);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the SHA256 hash of a file
|
||||
*
|
||||
|
@ -208,6 +176,18 @@ public class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource the internal resource to read off from
|
||||
* @return the byte array of an InputStream
|
||||
*/
|
||||
public static byte[] readAllBytes(String resource) {
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource(resource)) {
|
||||
return readAllBytes(stream);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error while trying to read internal input stream!", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stream the InputStream to read off of
|
||||
* @return the byte array of an InputStream
|
||||
|
@ -265,8 +245,8 @@ public class FileUtils {
|
|||
* @return a set of all the classes annotated by the given annotation
|
||||
*/
|
||||
public static Set<Class<?>> getGeneratedClassesForAnnotation(String input) {
|
||||
InputStream annotatedClass = FileUtils.getResource(input);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(annotatedClass));
|
||||
try (InputStream annotatedClass = GeyserImpl.getInstance().getBootstrap().getResource(input);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(annotatedClass))) {
|
||||
return reader.lines().map(className -> {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
|
@ -275,5 +255,8 @@ public class FileUtils {
|
|||
throw new RuntimeException(ex);
|
||||
}
|
||||
}).collect(Collectors.toSet());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue