forked from GeyserMC/Geyser
Merge pull request #275 from rtm516/server-language-processing
Server language processing
This commit is contained in:
commit
e1d1f9ee8a
15 changed files with 526 additions and 17 deletions
|
@ -101,6 +101,11 @@ public class GeyserBukkitConfiguration implements IGeyserConfiguration {
|
|||
return config.getBoolean("allow-third-party-capes", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLocale() {
|
||||
return config.getString("default-locale", "en_us");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getFloodgateKeyFile() {
|
||||
return Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem"));
|
||||
|
|
|
@ -102,6 +102,11 @@ public class GeyserBungeeConfiguration implements IGeyserConfiguration {
|
|||
return config.getBoolean("allow-third-party-capes", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLocale() {
|
||||
return config.getString("default-locale", "en_us");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getFloodgateKeyFile() {
|
||||
return Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem"));
|
||||
|
|
|
@ -105,6 +105,11 @@ public class GeyserSpongeConfiguration implements IGeyserConfiguration {
|
|||
return node.getNode("allow-third-party-capes").getBoolean(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultLocale() {
|
||||
return node.getNode("default-locale").getString("en_us");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getFloodgateKeyFile() {
|
||||
return Paths.get(dataFolder.toString(), node.getNode("floodgate-key-file").getString("public-key.pem"));
|
||||
|
|
|
@ -63,6 +63,9 @@ public class GeyserConfiguration implements IGeyserConfiguration {
|
|||
@JsonProperty("allow-third-party-capes")
|
||||
private boolean allowThirdPartyCapes;
|
||||
|
||||
@JsonProperty("default-locale")
|
||||
private String defaultLocale;
|
||||
|
||||
private MetricsInfo metrics;
|
||||
|
||||
@Override
|
||||
|
|
|
@ -63,6 +63,9 @@ public class GeyserVelocityConfiguration implements IGeyserConfiguration {
|
|||
@JsonProperty("allow-third-party-capes")
|
||||
private boolean allowThirdPartyCapes;
|
||||
|
||||
@JsonProperty("default-locale")
|
||||
private String defaultLocale;
|
||||
|
||||
private MetricsInfo metrics;
|
||||
|
||||
@Override
|
||||
|
|
|
@ -46,6 +46,8 @@ public interface IGeyserConfiguration {
|
|||
|
||||
boolean isAllowThirdPartyCapes();
|
||||
|
||||
String getDefaultLocale();
|
||||
|
||||
Path getFloodgateKeyFile();
|
||||
|
||||
IMetricsInfo getMetrics();
|
||||
|
|
|
@ -65,6 +65,7 @@ import org.geysermc.connector.network.session.cache.*;
|
|||
import org.geysermc.connector.network.translators.Registry;
|
||||
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||
import org.geysermc.connector.utils.ChunkUtils;
|
||||
import org.geysermc.connector.utils.LocaleUtils;
|
||||
import org.geysermc.connector.utils.Toolbox;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.EncryptionUtil;
|
||||
|
@ -252,6 +253,17 @@ public class GeyserSession implements CommandSender {
|
|||
connector.getLogger().info(authData.getName() + " (logged in as: " + protocol.getProfile().getName() + ")" + " has connected to remote java server on address " + remoteServer.getAddress());
|
||||
playerEntity.setUuid(protocol.getProfile().getId());
|
||||
playerEntity.setUsername(protocol.getProfile().getName());
|
||||
|
||||
String locale = clientData.getLanguageCode();
|
||||
|
||||
// Let the user know there locale may take some time to download
|
||||
// as it has to be extracted from a JAR
|
||||
if (locale.toLowerCase().equals("en_us") && !LocaleUtils.LOCALE_MAPPINGS.containsKey("en_us")) {
|
||||
sendMessage("Downloading your locale (en_us) this may take some time");
|
||||
}
|
||||
|
||||
// Download and load the language for the player
|
||||
LocaleUtils.downloadAndLoadLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,6 +34,8 @@ import com.github.steveice10.mc.protocol.data.message.TranslationMessage;
|
|||
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerChatPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Translator(packet = ServerChatPacket.class)
|
||||
public class JavaChatTranslator extends PacketTranslator<ServerChatPacket> {
|
||||
|
||||
|
@ -58,14 +60,20 @@ public class JavaChatTranslator extends PacketTranslator<ServerChatPacket> {
|
|||
break;
|
||||
}
|
||||
|
||||
String locale = session.getClientData().getLanguageCode();
|
||||
|
||||
if (packet.getMessage() instanceof TranslationMessage) {
|
||||
textPacket.setType(TextPacket.Type.TRANSLATION);
|
||||
textPacket.setNeedsTranslation(true);
|
||||
textPacket.setParameters(MessageUtils.getTranslationParams(((TranslationMessage) packet.getMessage()).getTranslationParams()));
|
||||
textPacket.setMessage(MessageUtils.getBedrockMessage(packet.getMessage()));
|
||||
|
||||
List<String> paramsTranslated = MessageUtils.getTranslationParams(((TranslationMessage) packet.getMessage()).getTranslationParams(), locale);
|
||||
textPacket.setParameters(paramsTranslated);
|
||||
|
||||
textPacket.setMessage(MessageUtils.insertParams(MessageUtils.getTranslatedBedrockMessage(packet.getMessage(), locale, false), paramsTranslated));
|
||||
} else {
|
||||
textPacket.setNeedsTranslation(false);
|
||||
textPacket.setMessage(MessageUtils.getBedrockMessage(packet.getMessage()));
|
||||
|
||||
textPacket.setMessage(MessageUtils.getTranslatedBedrockMessage(packet.getMessage(), locale, false));
|
||||
}
|
||||
|
||||
session.getUpstream().sendPacket(textPacket);
|
||||
|
|
|
@ -65,4 +65,23 @@ public class FileUtils {
|
|||
|
||||
return file;
|
||||
}
|
||||
|
||||
public static void writeFile(File file, char[] data) throws IOException {
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
|
||||
for (char c : data) {
|
||||
fos.write(c);
|
||||
}
|
||||
|
||||
fos.flush();
|
||||
fos.close();
|
||||
}
|
||||
|
||||
public static void writeFile(String name, char[] data) throws IOException {
|
||||
writeFile(new File(name), data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.utils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class LocaleUtils {
|
||||
|
||||
public static final Map<String, Map<String, String>> LOCALE_MAPPINGS = new HashMap<>();
|
||||
|
||||
private static final Map<String, Asset> ASSET_MAP = new HashMap<>();
|
||||
|
||||
private static final String DEFAULT_LOCALE = (GeyserConnector.getInstance().getConfig().getDefaultLocale() != null ? GeyserConnector.getInstance().getConfig().getDefaultLocale() : "en_us");
|
||||
|
||||
private static String smallestURL = "";
|
||||
|
||||
static {
|
||||
// Create the locales folder
|
||||
File localesFolder = new File("locales/");
|
||||
localesFolder.mkdir();
|
||||
|
||||
// Download the latest asset list and cache it
|
||||
generateAssetCache();
|
||||
downloadAndLoadLocale(DEFAULT_LOCALE);
|
||||
}
|
||||
|
||||
private static void generateAssetCache() {
|
||||
try {
|
||||
VersionManifest versionManifest = Toolbox.JSON_MAPPER.readValue(WebUtils.getBody("https://launchermeta.mojang.com/mc/game/version_manifest.json"), VersionManifest.class);
|
||||
String latestInfoURL = "";
|
||||
for (Version version : versionManifest.getVersions()) {
|
||||
if (version.getId().equals(versionManifest.getLatestVersion().getRelease())) {
|
||||
latestInfoURL = version.getUrl();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (latestInfoURL.isEmpty()) {
|
||||
throw new Exception("Unable to get latest Minecraft version");
|
||||
}
|
||||
|
||||
VersionInfo versionInfo = Toolbox.JSON_MAPPER.readValue(WebUtils.getBody(latestInfoURL), VersionInfo.class);
|
||||
|
||||
int currentSize = Integer.MAX_VALUE;
|
||||
for (VersionDownload download : versionInfo.getDownloads().values()) {
|
||||
if (download.getUrl().endsWith(".jar") && download.getSize() < currentSize) {
|
||||
smallestURL = download.getUrl();
|
||||
currentSize = download.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
JsonNode assets = Toolbox.JSON_MAPPER.readTree(WebUtils.getBody(versionInfo.getAssetIndex().getUrl())).get("objects");
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> assetIterator = assets.fields();
|
||||
while (assetIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = assetIterator.next();
|
||||
Asset asset = Toolbox.JSON_MAPPER.treeToValue(entry.getValue(), Asset.class);
|
||||
ASSET_MAP.put(entry.getKey(), asset);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
GeyserConnector.getInstance().getLogger().info("Failed to load locale asset cache: " + (!e.getMessage().isEmpty() ? e.getMessage() : e.getStackTrace()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void downloadAndLoadLocale(String locale) {
|
||||
locale = locale.toLowerCase();
|
||||
if (!ASSET_MAP.containsKey("minecraft/lang/" + locale + ".json") && !locale.equals("en_us")) {
|
||||
GeyserConnector.getInstance().getLogger().warning("Invalid locale requested to download and load: " + locale);
|
||||
return;
|
||||
}
|
||||
|
||||
GeyserConnector.getInstance().getLogger().debug("Downloading and loading locale: " + locale);
|
||||
|
||||
downloadLocale(locale);
|
||||
loadLocale(locale);
|
||||
}
|
||||
|
||||
private static void downloadLocale(String locale) {
|
||||
File localeFile = new File("locales/" + locale + ".json");
|
||||
|
||||
if (localeFile.exists()) {
|
||||
GeyserConnector.getInstance().getLogger().debug("Locale already downloaded: " + locale);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the en_us locale
|
||||
if (locale.equals("en_us")) {
|
||||
downloadEN_US(localeFile);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the hash and download the locale
|
||||
String hash = ASSET_MAP.get("minecraft/lang/" + locale + ".json").getHash();
|
||||
WebUtils.downloadFile("http://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash, "locales/" + locale + ".json");
|
||||
}
|
||||
|
||||
private static void loadLocale(String locale) {
|
||||
File localeFile = new File("locales/" + locale + ".json");
|
||||
|
||||
// Load the locale
|
||||
if (localeFile.exists()) {
|
||||
// Read the localefile
|
||||
InputStream localeStream;
|
||||
try {
|
||||
localeStream = new FileInputStream(localeFile);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new AssertionError("Unable to load locale: " + locale + " (" + e.getMessage() + ")");
|
||||
}
|
||||
|
||||
// Parse the file as json
|
||||
JsonNode localeObj;
|
||||
try {
|
||||
localeObj = Toolbox.JSON_MAPPER.readTree(localeStream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load Java lang map for " + locale, e);
|
||||
}
|
||||
|
||||
// Parse all the locale fields
|
||||
Iterator<Map.Entry<String, JsonNode>> localeIterator = localeObj.fields();
|
||||
Map<String, String> langMap = new HashMap<>();
|
||||
while (localeIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = localeIterator.next();
|
||||
langMap.put(entry.getKey(), entry.getValue().asText());
|
||||
}
|
||||
|
||||
// Insert the locale into the mappings
|
||||
LOCALE_MAPPINGS.put(locale.toLowerCase(), langMap);
|
||||
} else {
|
||||
GeyserConnector.getInstance().getLogger().warning("Missing locale file: " + locale);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadEN_US(File localeFile) {
|
||||
try {
|
||||
// Let the user know we are downloading the JAR
|
||||
GeyserConnector.getInstance().getLogger().info("Downloading Minecraft JAR to extract en_us locale, please wait... (this may take some time depending on the speed of your internet connection)");
|
||||
GeyserConnector.getInstance().getLogger().debug("Download URL: " + smallestURL);
|
||||
|
||||
// Download the smallest JAR (client or server)
|
||||
WebUtils.downloadFile(smallestURL, "tmp_locale.jar");
|
||||
|
||||
// Load in the JAR as a zip and extract the file
|
||||
ZipFile localeJar = new ZipFile("tmp_locale.jar");
|
||||
InputStream inputStream = localeJar.getInputStream(localeJar.getEntry("assets/minecraft/lang/en_us.json"));
|
||||
FileOutputStream outputStream = new FileOutputStream(localeFile);
|
||||
|
||||
// Write the file to the locale dir
|
||||
int data = inputStream.read();
|
||||
while(data != -1){
|
||||
outputStream.write(data);
|
||||
data = inputStream.read();
|
||||
}
|
||||
|
||||
// Flush all changes to disk and cleanup
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
inputStream.close();
|
||||
localeJar.close();
|
||||
|
||||
// Delete the nolonger needed client/server jar
|
||||
Files.delete(Paths.get("tmp_locale.jar"));
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to download and extract en_us locale!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getLocaleString(String messageText, String locale) {
|
||||
Map<String, String> localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(locale.toLowerCase());
|
||||
if (localeStrings == null)
|
||||
localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(DEFAULT_LOCALE);
|
||||
|
||||
return localeStrings.getOrDefault(messageText, messageText);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
class VersionManifest {
|
||||
@JsonProperty("latest")
|
||||
private LatestVersion latestVersion;
|
||||
|
||||
@JsonProperty("versions")
|
||||
private List<Version> versions;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
class LatestVersion {
|
||||
@JsonProperty("release")
|
||||
private String release;
|
||||
|
||||
@JsonProperty("snapshot")
|
||||
private String snapshot;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
class Version {
|
||||
@JsonProperty("id")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("type")
|
||||
private String type;
|
||||
|
||||
@JsonProperty("url")
|
||||
private String url;
|
||||
|
||||
@JsonProperty("time")
|
||||
private String time;
|
||||
|
||||
@JsonProperty("releaseTime")
|
||||
private String releaseTime;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
class VersionInfo {
|
||||
@JsonProperty("id")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("type")
|
||||
private String type;
|
||||
|
||||
@JsonProperty("time")
|
||||
private String time;
|
||||
|
||||
@JsonProperty("releaseTime")
|
||||
private String releaseTime;
|
||||
|
||||
@JsonProperty("assetIndex")
|
||||
private AssetIndex assetIndex;
|
||||
|
||||
@JsonProperty("downloads")
|
||||
private Map<String, VersionDownload> downloads;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
class VersionDownload {
|
||||
@JsonProperty("sha1")
|
||||
private String sha1;
|
||||
|
||||
@JsonProperty("size")
|
||||
private int size;
|
||||
|
||||
@JsonProperty("url")
|
||||
private String url;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
class AssetIndex {
|
||||
@JsonProperty("id")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("sha1")
|
||||
private String sha1;
|
||||
|
||||
@JsonProperty("size")
|
||||
private int size;
|
||||
|
||||
@JsonProperty("totalSize")
|
||||
private int totalSize;
|
||||
|
||||
@JsonProperty("url")
|
||||
private String url;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
class Asset {
|
||||
@JsonProperty("hash")
|
||||
private String hash;
|
||||
|
||||
@JsonProperty("size")
|
||||
private int size;
|
||||
}
|
|
@ -35,21 +35,24 @@ import com.google.gson.JsonElement;
|
|||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MessageUtils {
|
||||
|
||||
public static List<String> getTranslationParams(Message[] messages) {
|
||||
public static List<String> getTranslationParams(Message[] messages, String locale) {
|
||||
List<String> strings = new ArrayList<>();
|
||||
for (Message message : messages) {
|
||||
if (message instanceof TranslationMessage) {
|
||||
TranslationMessage translation = (TranslationMessage) message;
|
||||
|
||||
if (locale == null) {
|
||||
String builder = "%" + translation.getTranslationKey();
|
||||
strings.add(builder);
|
||||
}
|
||||
|
||||
if (translation.getTranslationKey().equals("commands.gamemode.success.other")) {
|
||||
strings.add("");
|
||||
|
@ -59,11 +62,16 @@ public class MessageUtils {
|
|||
strings.add(" - no permission or invalid command!");
|
||||
}
|
||||
|
||||
strings.addAll(getTranslationParams(translation.getTranslationParams()));
|
||||
List<String> furtherParams = getTranslationParams(translation.getTranslationParams());
|
||||
if (locale != null) {
|
||||
strings.add(insertParams(LocaleUtils.getLocaleString(translation.getTranslationKey(), locale), furtherParams));
|
||||
}else{
|
||||
strings.addAll(furtherParams);
|
||||
}
|
||||
} else {
|
||||
String builder = getFormat(message.getStyle().getFormats()) +
|
||||
getColor(message.getStyle().getColor()) +
|
||||
getBedrockMessage(message);
|
||||
getColor(message.getStyle().getColor());
|
||||
builder += getTranslatedBedrockMessage(message, locale, false);
|
||||
strings.add(builder);
|
||||
}
|
||||
}
|
||||
|
@ -71,29 +79,63 @@ public class MessageUtils {
|
|||
return strings;
|
||||
}
|
||||
|
||||
public static List<String> getTranslationParams(Message[] messages) {
|
||||
return getTranslationParams(messages, null);
|
||||
}
|
||||
|
||||
public static String getTranslationText(TranslationMessage message) {
|
||||
return getFormat(message.getStyle().getFormats()) + getColor(message.getStyle().getColor())
|
||||
+ "%" + message.getTranslationKey();
|
||||
}
|
||||
|
||||
public static String getBedrockMessage(Message message) {
|
||||
public static String getTranslatedBedrockMessage(Message message, String locale, boolean shouldTranslate) {
|
||||
JsonParser parser = new JsonParser();
|
||||
if (isMessage(message.getText())) {
|
||||
JsonObject object = parser.parse(message.getText()).getAsJsonObject();
|
||||
message = Message.fromJson(formatJson(object));
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder(message.getText());
|
||||
String messageText = message.getText();
|
||||
if (locale != null && shouldTranslate) {
|
||||
messageText = LocaleUtils.getLocaleString(messageText, locale);
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder(messageText);
|
||||
for (Message msg : message.getExtra()) {
|
||||
builder.append(getFormat(msg.getStyle().getFormats()));
|
||||
builder.append(getColor(msg.getStyle().getColor()));
|
||||
if (!(msg.getText() == null)) {
|
||||
builder.append(getBedrockMessage(msg));
|
||||
boolean isTranslationMessage = (msg instanceof TranslationMessage);
|
||||
builder.append(getTranslatedBedrockMessage(msg, locale, isTranslationMessage));
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static String getBedrockMessage(Message message) {
|
||||
return getTranslatedBedrockMessage(message, null, false);
|
||||
}
|
||||
|
||||
public static String insertParams(String message, List<String> params) {
|
||||
String newMessage = message;
|
||||
|
||||
Pattern p = Pattern.compile("%([1-9])\\$s");
|
||||
Matcher m = p.matcher(message);
|
||||
while (m.find()) {
|
||||
try {
|
||||
newMessage = newMessage.replaceFirst("%" + m.group(1) + "\\$s" , params.get(Integer.parseInt(m.group(1)) - 1));
|
||||
} catch (Exception e) {
|
||||
// Couldnt find the param to replace
|
||||
}
|
||||
}
|
||||
|
||||
for (String text : params) {
|
||||
newMessage = newMessage.replaceFirst("%s", text);
|
||||
}
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
private static String getColor(ChatColor color) {
|
||||
String base = "\u00a7";
|
||||
switch (color) {
|
||||
|
|
|
@ -40,7 +40,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.translators.item.ItemEntry;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Toolbox {
|
||||
|
@ -52,6 +52,8 @@ public class Toolbox {
|
|||
|
||||
public static final Int2ObjectMap<ItemEntry> ITEM_ENTRIES = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
public static final Map<String, Map<String, String>> LOCALE_MAPPINGS = new HashMap<>();
|
||||
|
||||
static {
|
||||
/* Load biomes */
|
||||
InputStream biomestream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/biome_definitions.dat");
|
||||
|
@ -103,6 +105,9 @@ public class Toolbox {
|
|||
entry.getValue().get("bedrock_id").intValue(), entry.getValue().get("bedrock_data").intValue()));
|
||||
itemIndex++;
|
||||
}
|
||||
|
||||
// Load the locale data
|
||||
LocaleUtils.init();
|
||||
}
|
||||
|
||||
public static InputStream getResource(String resource) {
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.utils;
|
||||
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
public class WebUtils {
|
||||
|
||||
public static String getBody(String reqURL) {
|
||||
URL url = null;
|
||||
try {
|
||||
url = new URL(reqURL);
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer content = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
content.append(inputLine);
|
||||
content.append("\n");
|
||||
}
|
||||
|
||||
in.close();
|
||||
con.disconnect();
|
||||
|
||||
return content.toString();
|
||||
} catch (Exception e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public static void downloadFile(String reqURL, String fileLocation) {
|
||||
try {
|
||||
InputStream in = new URL(reqURL).openStream();
|
||||
Files.copy(in, Paths.get(fileLocation), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to download and save file: " + fileLocation + " (" + reqURL + ")", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,6 +57,9 @@ general-thread-pool: 32
|
|||
# OptiFine capes, LabyMod capes, 5Zig capes and MinecraftCapes
|
||||
allow-third-party-capes: true
|
||||
|
||||
# The default locale if we dont have the one the client requested
|
||||
default-locale: en_us
|
||||
|
||||
# bStats is a stat tracker that is entirely anonymous and tracks only basic information
|
||||
# about Geyser, such as how many people are online, how many servers are using Geyser,
|
||||
# what OS is being used, etc. You can learn more about bStats here: https://bstats.org/.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 278c73449aeeb4064c7513a68f98a49a5f463f0a
|
||||
Subproject commit efc9db6b7d51bdf145230933ac23b321ac1c132d
|
Loading…
Reference in a new issue