From 142b2c8d4deda9632aee5d309796157b272a2b7e Mon Sep 17 00:00:00 2001 From: CrushedPixel Date: Wed, 29 Apr 2015 16:57:18 +0200 Subject: [PATCH] Translations are now automatically downloaded from the Replay Mod API Localized missing Strings --- .../eu/crushedpixel/replaymod/ReplayMod.java | 23 +++++++ .../replaymod/api/client/ApiClient.java | 7 ++ .../replaymod/api/client/ApiMethods.java | 2 +- .../replaymod/events/GuiEventHandler.java | 24 +++---- .../replaymod/events/GuiReplayOverlay.java | 5 +- .../localization/LocalizedResourcePack.java | 66 +++++++++++++++++++ .../assets/replaymod/lang/en_US.lang | 13 +++- 7 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java index e7ae1186..25477d2d 100755 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java @@ -3,7 +3,9 @@ package eu.crushedpixel.replaymod; import eu.crushedpixel.replaymod.api.client.ApiClient; import eu.crushedpixel.replaymod.chat.ChatMessageHandler; import eu.crushedpixel.replaymod.events.*; +import eu.crushedpixel.replaymod.localization.LocalizedResourcePack; import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; +import eu.crushedpixel.replaymod.reflection.MCPNames; import eu.crushedpixel.replaymod.registry.FileCopyHandler; import eu.crushedpixel.replaymod.registry.KeybindRegistry; import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer; @@ -23,6 +25,8 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import org.apache.commons.io.FilenameUtils; import java.io.File; +import java.lang.reflect.Field; +import java.util.List; @Mod(modid = ReplayMod.MODID, version = ReplayMod.VERSION) public class ReplayMod { @@ -59,6 +63,16 @@ public class ReplayMod { public static int TP_DISTANCE_LIMIT = 128; public static FileCopyHandler fileCopyHandler; + private static Field defaultResourcePacksField; + static { + try { + defaultResourcePacksField = Minecraft.class.getDeclaredField(MCPNames.field("field_110449_ao")); + defaultResourcePacksField.setAccessible(true); + } catch(Exception e) { + e.printStackTrace(); + } + } + // The instance of your mod that Forge uses. @Instance(value = "ReplayModID") public static ReplayMod instance; @@ -109,6 +123,15 @@ public class ReplayMod { //clean up replay_recordings folder removeTmcprFiles(); + try { + List rps = (List) defaultResourcePacksField.get(mc); + rps.add(new LocalizedResourcePack()); + defaultResourcePacksField.set(mc, rps); + mc.refreshResources(); + } catch(Exception e) { + e.printStackTrace(); + } + /* boolean auth = false; try { diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java index 916810fe..bbbbb06e 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiClient.java @@ -71,6 +71,13 @@ public class ApiClient { return info; } + public String getTranslation(String languageCode) throws IOException, ApiException { + QueryBuilder builder = new QueryBuilder(ApiMethods.get_language); + builder.put("language", languageCode); + String properties = SimpleApiClient.invokeUrl(builder.toString()); + return properties; + } + public void downloadThumbnail(int file, File target) throws IOException { QueryBuilder builder = new QueryBuilder(ApiMethods.get_thumbnail); builder.put("id", file); diff --git a/src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java index 029d64cb..0499c0f9 100755 --- a/src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java +++ b/src/main/java/eu/crushedpixel/replaymod/api/client/ApiMethods.java @@ -12,5 +12,5 @@ public class ApiMethods { public static final String remove_file = "remove_file"; public static final String rate_file = "rate_file"; public static final String check_auth = "check_auth"; - + public static final String get_language = "get_language"; } diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java index ff8f0ee7..d88fe160 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiEventHandler.java @@ -24,7 +24,7 @@ import eu.crushedpixel.replaymod.video.VideoWriter; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.*; import net.minecraft.client.gui.inventory.GuiInventory; -import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.resources.I18n; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiScreenEvent.ActionPerformedEvent; import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent; @@ -95,22 +95,22 @@ public class GuiEventHandler { @SubscribeEvent public void onDraw(DrawScreenEvent e) { if(e.gui instanceof GuiMainMenu) { - e.gui.drawString(mc.fontRendererObj, "Replay Mod:", 5, 5, Color.WHITE.getRGB()); + e.gui.drawString(mc.fontRendererObj, I18n.format("replaymod.title")+":", 5, 5, Color.WHITE.getRGB()); if(AuthenticationHandler.isAuthenticated()) { - e.gui.drawString(mc.fontRendererObj, "LOGGED IN", 5, 15, DARK_GREEN.getRGB()); + e.gui.drawString(mc.fontRendererObj, I18n.format("replaymod.gui.loggedin").toUpperCase(), 5, 15, DARK_GREEN.getRGB()); } else { - e.gui.drawString(mc.fontRendererObj, "LOGGED OUT", 5, 15, DARK_RED.getRGB()); + e.gui.drawString(mc.fontRendererObj, I18n.format("replaymod.gui.loggedout").toUpperCase(), 5, 15, DARK_RED.getRGB()); } if(replayCount == 0) { if(editorButton.isMouseOver()) { Point mouse = MouseUtils.getMousePos(); - e.gui.drawCenteredString(mc.fontRendererObj, "At least one Replay required", (int) mouse.getX(), (int) mouse.getY() + 4, Color.RED.getRGB()); + e.gui.drawCenteredString(mc.fontRendererObj, I18n.format("replaymod.gui.morereplays"), (int) mouse.getX(), (int) mouse.getY() + 4, Color.RED.getRGB()); } } else if(!VersionValidator.isValid) { if(editorButton.isMouseOver()) { Point mouse = MouseUtils.getMousePos(); - e.gui.drawCenteredString(mc.fontRendererObj, "Java 1.7 or newer required", (int) mouse.getX(), (int) mouse.getY() + 4, Color.RED.getRGB()); + e.gui.drawCenteredString(mc.fontRendererObj, I18n.format("replaymod.gui.java"), (int) mouse.getX(), (int) mouse.getY() + 4, Color.RED.getRGB()); } } } @@ -121,7 +121,7 @@ public class GuiEventHandler { if(event.gui instanceof GuiIngameMenu && ReplayHandler.isInReplay()) { for(GuiButton b : new ArrayList(event.buttonList)) { if(b.id == 1) { - b.displayString = "Exit Replay"; + b.displayString = I18n.format("replaymod.gui.exit"); b.yPosition -= 24 * 2; b.id = GuiConstants.EXIT_REPLAY_BUTTON; } else if(b.id >= 5 && b.id <= 7) { @@ -139,27 +139,27 @@ public class GuiEventHandler { } } - GuiButton rm = new GuiButton(GuiConstants.REPLAY_MANAGER_BUTTON_ID, event.gui.width / 2 - 100, i1 + 2 * 24, "Replay Viewer"); + GuiButton rm = new GuiButton(GuiConstants.REPLAY_MANAGER_BUTTON_ID, event.gui.width / 2 - 100, i1 + 2 * 24, I18n.format("replaymod.gui.replayviewer")); rm.width = rm.width / 2 - 2; //rm.enabled = AuthenticationHandler.isAuthenticated(); event.buttonList.add(rm); replayCount = ReplayFileIO.getAllReplayFiles().size(); - GuiButton re = new GuiButton(GuiConstants.REPLAY_EDITOR_BUTTON_ID, event.gui.width / 2 + 2, i1 + 2 * 24, "Replay Editor"); + GuiButton re = new GuiButton(GuiConstants.REPLAY_EDITOR_BUTTON_ID, event.gui.width / 2 + 2, i1 + 2 * 24, I18n.format("replaymod.gui.replayeditor")); re.width = re.width / 2 - 2; re.enabled = VersionValidator.isValid && replayCount > 0; event.buttonList.add(re); editorButton = re; - GuiButton rc = new GuiButton(GuiConstants.REPLAY_CENTER_BUTTON_ID, event.gui.width / 2 - 100, i1 + 3 * 24, "Replay Center"); + GuiButton rc = new GuiButton(GuiConstants.REPLAY_CENTER_BUTTON_ID, event.gui.width / 2 - 100, i1 + 3 * 24, I18n.format("replaymod.gui.replaycenter")); rc.enabled = true; event.buttonList.add(rc); } else if(event.gui instanceof GuiOptions) { event.buttonList.add(new GuiButton(GuiConstants.REPLAY_OPTIONS_BUTTON_ID, - event.gui.width / 2 - 155, event.gui.height / 6 + 48 - 6 - 24, 310, 20, "Replay Mod Settings...")); + event.gui.width / 2 - 155, event.gui.height / 6 + 48 - 6 - 24, 310, 20, I18n.format("replaymod.gui.settings.title"))); } } @@ -193,7 +193,7 @@ public class GuiEventHandler { ReplayHandler.lastExit = System.currentTimeMillis(); mc.theWorld.sendQuittingDisconnectingPacket(); - mc.loadWorld((WorldClient) null); + mc.loadWorld(null); mc.displayGuiScreen(new GuiMainMenu()); ReplayGuiRegistry.show(); diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java index 6b94abad..ebdfe223 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java @@ -22,6 +22,7 @@ import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.GuiInventory; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.RenderGameOverlayEvent; @@ -89,7 +90,7 @@ public class GuiReplayOverlay extends Gui { mc.displayGuiScreen(null); } ReplayHandler.setRealTimelineCursor(0); - speedSlider = new GuiReplaySpeedSlider(1, sliderX, sliderY, "Speed"); + speedSlider = new GuiReplaySpeedSlider(1, sliderX, sliderY, I18n.format("replaymod.gui.speed")); } @SubscribeEvent @@ -110,7 +111,7 @@ public class GuiReplayOverlay extends Gui { @SubscribeEvent public void renderRecordingIndicator(RenderGameOverlayEvent.Text event) { if(!ReplayHandler.isInReplay() && ReplayMod.replaySettings.showRecordingIndicator() && ConnectionEventHandler.isRecording()) { - this.drawString(mc.fontRendererObj, "RECORDING", 30, 18 - (mc.fontRendererObj.FONT_HEIGHT / 2), Color.WHITE.getRGB()); + this.drawString(mc.fontRendererObj, I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (mc.fontRendererObj.FONT_HEIGHT / 2), Color.WHITE.getRGB()); mc.renderEngine.bindTexture(replay_gui); GlStateManager.resetColor(); GlStateManager.enableAlpha(); diff --git a/src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java b/src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java new file mode 100644 index 00000000..a82d9d97 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/localization/LocalizedResourcePack.java @@ -0,0 +1,66 @@ +package eu.crushedpixel.replaymod.localization; + +import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableSet; +import eu.crushedpixel.replaymod.ReplayMod; +import net.minecraft.client.resources.IResourcePack; +import net.minecraft.client.resources.data.IMetadataSection; +import net.minecraft.client.resources.data.IMetadataSerializer; +import net.minecraft.util.ResourceLocation; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class LocalizedResourcePack implements IResourcePack { + + private Map availableLanguages = new HashMap(); + + @Override + public InputStream getInputStream(ResourceLocation loc) { + if(!loc.getResourcePath().endsWith(".lang")) return null; + String langcode = loc.getResourcePath().split("/")[1].split("\\.")[0]; + if(availableLanguages.containsKey(langcode)) return new ByteArrayInputStream(availableLanguages.get(langcode).getBytes(Charsets.UTF_8)); + return null; + } + + @Override + public boolean resourceExists(ResourceLocation loc) { + if(!(loc.getResourcePath().endsWith(".lang"))) return false; + String langcode = loc.getResourcePath().split("/")[1].split("\\.")[0]; + boolean downloaded = true; + try { + String lang = ReplayMod.apiClient.getTranslation(langcode); + availableLanguages.put(langcode, lang); + } catch(Exception e) { + e.printStackTrace(); + downloaded = false; + } + + return downloaded; + } + + @Override + public Set getResourceDomains() { + return ImmutableSet.of("minecraft", "replaymod"); + } + + @Override + public IMetadataSection getPackMetadata(IMetadataSerializer p_135058_1_, String p_135058_2_) throws IOException { + return null; + } + + @Override + public BufferedImage getPackImage() throws IOException { + return null; + } + + @Override + public String getPackName() { + return "ReplayModLocalizationResourcePack"; + } +} diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index 4e64e29b..ecd41262 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -1,3 +1,5 @@ +replaymod.title=Replay Mod + #All of the chat messages replaymod.chat.recordingstarted=Recording started replaymod.chat.recordingfailed=Failed to start recording @@ -37,6 +39,15 @@ replaymod.gui.add=Add replaymod.gui.start=Start replaymod.gui.end=End replaymod.gui.delete=Delete +replaymod.gui.recording=Recording +replaymod.gui.speed=Speed + +replaymod.gui.exit=Exit Replay +replaymod.gui.java=Java 1.7 or newer required +replaymod.gui.morereplays=At least one Replay required + +replaymod.gui.loggedin=LOGGED IN +replaymod.gui.loggedout=LOGGED OUT replaymod.gui.mainmenu=Main Menu replaymod.gui.settings=Settings @@ -90,7 +101,7 @@ replaymod.gui.editor.modify.title=Modify Replay replaymod.gui.editor.trim.description=Removes the beginning and end of a Replay File, only keeping the Replay between the given timestamps replaymod.gui.editor.connect.description=Connects multiple Replays in the specified order -replaymod.gui.editor.modify.description +replaymod.gui.editor.modify.description=Provides several filters to modify Replay Files #Spectate Player GUI replaymod.gui.spectate.title=Spectate Player