diff --git a/.gitignore b/.gitignore index dafe649..e88bfc3 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ build run .DS_Store Thumbs.db +.gradletasknamecache \ No newline at end of file diff --git a/build.gradle b/build.gradle index 64a061e..24bfd7f 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,7 @@ minecraft { replace "@VERSION@", project.version replaceIn "org/dimdev/riftloader/Main.java" + replaceIn "org/dimdev/rift/mixin/core/client/MixinMainMenu.java" } mixin { @@ -75,6 +76,10 @@ processResources { expand 'version': project.version } + filesMatching('riftmod.json') { + expand 'version': project.version + } + // Re-run this task when these change inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version diff --git a/src/main/java/org/dimdev/rift/mixin/core/MixinMinecraftServer.java b/src/main/java/org/dimdev/rift/mixin/core/MixinMinecraftServer.java index 87a6f29..6ca6831 100644 --- a/src/main/java/org/dimdev/rift/mixin/core/MixinMinecraftServer.java +++ b/src/main/java/org/dimdev/rift/mixin/core/MixinMinecraftServer.java @@ -1,13 +1,38 @@ package org.dimdev.rift.mixin.core; +import net.minecraft.command.CommandSource; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.world.WorldServer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(MinecraftServer.class) public class MixinMinecraftServer { + @Shadow + public WorldServer[] worlds; + @Overwrite public String getServerModName() { return "rift"; } + + @Inject( + method = "getCommandSource", + at = @At(value = "NEW"), + cancellable = true + ) + private void beforeNew(CallbackInfoReturnable ci) { + if(worlds == null) { // World has not been loaded yet, this might happen when the datapack is loaded for the first time + ci.setReturnValue(new CommandSource((MinecraftServer) (Object) this, Vec3d.ZERO, Vec2f.ZERO, null, 4, "Server", + new TextComponentString("Server"), (MinecraftServer) (Object) this, null)); + ci.cancel(); + } + } } diff --git a/src/main/java/org/dimdev/rift/mixin/core/client/MixinMainMenu.java b/src/main/java/org/dimdev/rift/mixin/core/client/MixinMainMenu.java new file mode 100644 index 0000000..61c7459 --- /dev/null +++ b/src/main/java/org/dimdev/rift/mixin/core/client/MixinMainMenu.java @@ -0,0 +1,136 @@ +package org.dimdev.rift.mixin.core.client; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiMainMenu; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderSkybox; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Util; +import net.minecraft.util.math.MathHelper; +import org.dimdev.rift.modlist.ModList; +import org.dimdev.riftloader.RiftLoader; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GuiMainMenu.class) +public abstract class MixinMainMenu extends GuiScreen { + + @Shadow + private void switchToRealms() { + } + + @Shadow @Final private RenderSkybox panorama; + @Shadow @Final private float minceraftRoll; + @Shadow @Final private static ResourceLocation MINECRAFT_TITLE_TEXTURES; + @Shadow @Final private static ResourceLocation MINECRAFT_TITLE_EDITION; + @Shadow private String splashText; + @Shadow private int widthCopyrightRest; + @Shadow private int widthCopyright; + @Shadow private String openGLWarning1; + @Shadow private int openGLWarningX1; + @Shadow private int openGLWarningY1; + @Shadow private int openGLWarningX2; + @Shadow private int openGLWarningY2; + @Shadow private String openGLWarning2; + @Shadow private int openGLWarning2Width; + @Shadow private GuiScreen realmsNotification; + + @Shadow protected abstract boolean areRealmsNotificationsEnabled(); + + @Override + public void render(int p_render_1_, int p_render_2_, float p_render_3_) { + this.panorama.render(p_render_3_); + int lvt_5_1_ = this.width / 2 - 137; + this.mc.getTextureManager().bindTexture(new ResourceLocation("textures/gui/title/background/panorama_overlay.png")); + drawScaledCustomSizeModalRect(0, 0, 0.0F, 0.0F, 16, 128, this.width, this.height, 16.0F, 128.0F); + this.mc.getTextureManager().bindTexture(MINECRAFT_TITLE_TEXTURES); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + if ((double) minceraftRoll < 1.0E-4D) { + this.drawTexturedModalRect(lvt_5_1_, 30, 0, 0, 99, 44); + this.drawTexturedModalRect(lvt_5_1_ + 99, 30, 129, 0, 27, 44); + this.drawTexturedModalRect(lvt_5_1_ + 99 + 26, 30, 126, 0, 3, 44); + this.drawTexturedModalRect(lvt_5_1_ + 99 + 26 + 3, 30, 99, 0, 26, 44); + this.drawTexturedModalRect(lvt_5_1_ + 155, 30, 0, 45, 155, 44); + } else { + this.drawTexturedModalRect(lvt_5_1_, 30, 0, 0, 155, 44); + this.drawTexturedModalRect(lvt_5_1_ + 155, 30, 0, 45, 155, 44); + } + + this.mc.getTextureManager().bindTexture(MINECRAFT_TITLE_EDITION); + drawModalRectWithCustomSizedTexture(lvt_5_1_ + 88, 67, 0.0F, 0.0F, 98, 14, 128.0F, 16.0F); + GlStateManager.pushMatrix(); + GlStateManager.translatef((float)(this.width / 2 + 90), 70.0F, 0.0F); + GlStateManager.rotatef(-20.0F, 0.0F, 0.0F, 1.0F); + float lvt_7_1_ = 1.8F - MathHelper.abs(MathHelper.sin((float)(Util.milliTime() % 1000L) / 1000.0F * 6.2831855F) * 0.1F); + lvt_7_1_ = lvt_7_1_ * 100.0F / (float)(this.fontRenderer.getStringWidth(this.splashText) + 32); + GlStateManager.scalef(lvt_7_1_, lvt_7_1_, lvt_7_1_); + this.drawCenteredString(this.fontRenderer, this.splashText, 0, -8, -256); + GlStateManager.popMatrix(); + String lvt_8_1_ = "Minecraft 1.13.2"; + if (this.mc.isDemo()) { + lvt_8_1_ = lvt_8_1_ + " Demo"; + } else { + lvt_8_1_ = lvt_8_1_ + ("release".equalsIgnoreCase(this.mc.getVersionType()) ? "" : "/" + this.mc.getVersionType()); + } + + this.drawString(this.fontRenderer, lvt_8_1_, 2, this.height - 30, -1); + this.drawString(this.fontRenderer, "Powered By Rift @VERSION@", 2, this.height - 20, -1); + this.drawString(this.fontRenderer, String.format("%s mods loaded", RiftLoader.instance.getMods().size()), 2, this.height - 10, -1); + + + this.drawString(this.fontRenderer, "Copyright Mojang AB. Do not distribute!", this.widthCopyrightRest, this.height - 10, -1); + if (p_render_1_ > this.widthCopyrightRest && p_render_1_ < this.widthCopyrightRest + this.widthCopyright && p_render_2_ > this.height - 10 && p_render_2_ < this.height) { + drawRect(this.widthCopyrightRest, this.height - 1, this.widthCopyrightRest + this.widthCopyright, this.height, -1); + } + + if (this.openGLWarning1 != null && !this.openGLWarning1.isEmpty()) { + drawRect(this.openGLWarningX1 - 2, this.openGLWarningY1 - 2, this.openGLWarningX2 + 2, this.openGLWarningY2 - 1, 1428160512); + this.drawString(this.fontRenderer, this.openGLWarning1, this.openGLWarningX1, this.openGLWarningY1, -1); + this.drawString(this.fontRenderer, this.openGLWarning2, (this.width - this.openGLWarning2Width) / 2, this.openGLWarningY1 + 12, -1); + } + + super.render(p_render_1_, p_render_2_, p_render_3_); + if (this.areRealmsNotificationsEnabled()) { + this.realmsNotification.render(p_render_1_, p_render_2_, p_render_3_); + } + } + + + @ModifyArg( + method = "addSingleplayerMultiplayerButtons", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/GuiMainMenu;addButton(Lnet/minecraft/client/gui/GuiButton;)Lnet/minecraft/client/gui/GuiButton;", + ordinal = 2 + ) + ) + private GuiButton getRealmsButton(GuiButton original) { + GuiButton button = new GuiButton(original.id, width / 2 + 2, original.y, 98, 20, I18n.format("menu.online")) { + @Override + public void onClick(double mouseX, double mouseY) { + switchToRealms(); + } + }; + return button; + } + + @Inject(method = "addSingleplayerMultiplayerButtons", at = @At("RETURN")) + private void onAddSingleplayerMultiplayerButtons(int y, int dy, CallbackInfo ci) { + GuiButton button = new GuiButton(100, width / 2 - 100, y + dy * 2, 98, 20, I18n.format("rift.modlist.mods")) { + @Override + public void onClick(double mouseX, double mouseY) { + ModList.displayModList(); + } + }; + addButton(button); + } + +} diff --git a/src/main/java/org/dimdev/rift/modlist/GuiMods.java b/src/main/java/org/dimdev/rift/modlist/GuiMods.java new file mode 100644 index 0000000..d3a1643 --- /dev/null +++ b/src/main/java/org/dimdev/rift/modlist/GuiMods.java @@ -0,0 +1,108 @@ +package org.dimdev.rift.modlist; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.Util; +import org.dimdev.riftloader.ModInfo; +import org.dimdev.riftloader.RiftLoader; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class GuiMods extends GuiScreen { + + private final String searchBoxSuggestion = I18n.format("rift.modlist.search_mods"); + public static List modList = new ArrayList<>(); + + @Nullable + private GuiModsContent guiModListContent; + private GuiTextField searchBox; + public GuiScreen previousGui; + + public GuiMods() { + regenerateMods(); + } + + private void regenerateMods() { + modList = new ArrayList<>(); + RiftLoader.instance.getMods().forEach(modInfo -> { + ModInfo cloned = new ModInfo(); + cloned.id = modInfo.id; + cloned.name = modInfo.name != null ? modInfo.name : modInfo.id; + cloned.source = modInfo.source; + cloned.authors = modInfo.authors; + cloned.listeners = modInfo.listeners; + modList.add(modInfo); + }); + Collections.sort(modList, (riftMod, anotherMod) -> { + return riftMod.name.compareTo(anotherMod.name); + }); + } + + @Override + protected void initGui() { + Minecraft.getInstance().keyboardListener.enableRepeatEvents(true); + addButton(new GuiButton(501, this.width / 2 - 100, this.height - 30, 93, 20, I18n.format("rift.modlist.openFolder")) { + @Override + public void onClick(double mouseX, double mouseY) { + Util.getOSType().openFile(RiftLoader.instance.modsDir); + } + }); + this.guiModListContent = new GuiModsContent(this, ""); + + this.searchBox = new GuiTextField(103, this.fontRenderer, this.width / 2 - 100, 32, 200, 20) { + @Override + public void setFocused(boolean var1) { + super.setFocused(true); + } + }; + this.searchBox.setTextAcceptHandler((p_212350_1_, p_212350_2_) -> + { + this.guiModListContent.searchFilter(p_212350_2_); + }); + addButton(new GuiButton(104, this.width / 2 - 3, this.height - 30, 93, 20, I18n.format("rift.modlist.done")) { + @Override + public void onClick(double var1, double var3) { + close(); + Minecraft.getInstance().displayGuiScreen(previousGui); + } + }); + this.children.add(searchBox); + this.children.add(guiModListContent); + this.searchBox.setFocused(true); + this.searchBox.setCanLoseFocus(false); + } + + public void reloadSearch() { + try { + this.searchBox.setText(""); + this.guiModListContent.searchFilter(""); + } catch (Exception e) { + } + } + + @Override + public void tick() { + this.searchBox.tick(); + this.searchBox.setSuggestion(searchBox.getText().equals("") ? searchBoxSuggestion : null); + } + + @Override + public void render(int mouseX, int mouseY, float partialTicks) { + this.guiModListContent.drawScreen(mouseX, mouseY, partialTicks); + this.searchBox.drawTextField(mouseX, mouseY, partialTicks); + this.drawCenteredString(this.fontRenderer, I18n.format("rift.modlist.mods"), this.width / 2, 16, 16777215); + super.render(mouseX, mouseY, partialTicks); + } + + @Nullable + public GuiModsContent getGuiModListContent() { + return guiModListContent; + } + +} diff --git a/src/main/java/org/dimdev/rift/modlist/GuiModsContent.java b/src/main/java/org/dimdev/rift/modlist/GuiModsContent.java new file mode 100644 index 0000000..5eef5bf --- /dev/null +++ b/src/main/java/org/dimdev/rift/modlist/GuiModsContent.java @@ -0,0 +1,175 @@ +package org.dimdev.rift.modlist; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.SimpleSound; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiSlot; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.init.SoundEvents; +import org.dimdev.riftloader.ModInfo; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class GuiModsContent extends GuiSlot { + + private List modList = new ArrayList<>(); + private GuiMods parent; + private FontRenderer fontRenderer; + private int currentIndex = -1; + + public GuiModsContent(GuiMods parent, String searchTerm) { + super( + Minecraft.getInstance(), + parent.width, + parent.height, + 60, + parent.height - 40, + 40 + ); + this.parent = parent; + this.modList = new ArrayList<>(); + this.fontRenderer = mc.fontRenderer; + setShowSelectionBox(true); + searchFilter(searchTerm); + } + + @Override + public int getListWidth() { + return this.width - 48 * 2; + } + + public int getCurrentIndex() { + return currentIndex; + } + + public List getModList() { + return modList; + } + + @Override + protected int getSize() { + return modList.size(); + } + + @Override + protected boolean isSelected(int slotIndex) { + return slotIndex == currentIndex; + } + + @Override + protected void drawBackground() { + parent.drawDefaultBackground(); + } + + protected int getY(int index) { + return top + 4 - getAmountScrolled() + index * slotHeight + headerPadding; + } + + protected int getX(int index) { + return left + width / 2 - getListWidth() / 2 + 2; + } + + @Override + protected void drawSlot(int slotIndex, int xPos, int yPos, int heightIn, int mouseXIn, int mouseYIn, float partialTicks) { + int i = this.getY(slotIndex); + int j = this.getX(slotIndex); + ModInfo mod = modList.get(slotIndex); + Minecraft.getInstance().getTextureManager().bindTexture(ModList.getModIcon(mod.id, mod.source)); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + Gui.drawModalRectWithCustomSizedTexture(j, i, 0, 0, 32, 32, 32, 32); + String modName = mod.name; + int j1 = fontRenderer.getStringWidth(modName); + if (j1 > 157) + modName = fontRenderer.trimStringToWidth(modName, 157 - fontRenderer.getStringWidth("...")) + "..."; + this.fontRenderer.drawStringWithShadow(modName, (float) (j + 32 + 2), (float) (i + 1), 16777215); + String authors = I18n.format("rift.modlist.authors"); + for(String name : mod.authors) { + authors += " " + name; + } + if (mod.authors.size() == 0) authors += " " + I18n.format("rift.modlist.noone"); + List list = fontRenderer.listFormattedStringToWidth(authors, 157); + for(String l : list) { + fontRenderer.drawStringWithShadow(l, (float) (j + 32 + 2), (float) (i + 12 + 10 * list.indexOf(l)), 8421504); + } + GuiButton viewButton = new GuiButton(700 + slotIndex, left + width / 2 + getListWidth() / 2 - 61, i + 6, 50, 20, + I18n.format("rift.modlist.view")) { + }; + viewButton.render(mouseXIn, mouseYIn, partialTicks); + } + + @Override + protected int getContentHeight() { + return this.getSize() * 40; + } + + @Override + public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) { + int x = left + width / 2 + getListWidth() / 2 - 61, y = 0, index = 0; + while (true) { + if (getY(index) > p_mouseClicked_3_) { + index--; + y = getY(index); + break; + } + index++; + } + if (p_mouseClicked_1_ > x && p_mouseClicked_1_ < x + 50 && p_mouseClicked_3_ > y + 6 && p_mouseClicked_3_ < y + 26) { + Minecraft.getInstance().getSoundHandler().play(SimpleSound.master(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + Minecraft.getInstance().displayGuiScreen(new GuiModsView(modList.get(index))); + currentIndex = -1; + } else if (isMouseInList(p_mouseClicked_1_, p_mouseClicked_3_)) { + Minecraft.getInstance().getSoundHandler().play(SimpleSound.master(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + currentIndex = index; + } + return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_); + } + + public boolean isMouseInList(double p_mouseClicked_1_, double p_mouseClicked_3_) { + return p_mouseClicked_3_ > 40 && p_mouseClicked_3_ < parent.height - 40; + } + + @Override + protected int getScrollBarX() { + return this.width - 46; + } + + public void setCurrentIndex(int currentIndex) { + this.currentIndex = currentIndex; + } + + public void searchFilter(String searchTerm) { + String currentId = currentIndex > 0 ? modList.get(currentIndex).id : ""; + List modList = new ArrayList<>(); + if (searchTerm.replaceAll(" ", "").equals("")) + modList = new LinkedList<>(GuiMods.modList); + else + for(ModInfo mod : GuiMods.modList) { + List list = new LinkedList<>(mod.authors); + list.addAll(Arrays.asList(mod.id, mod.name, mod.source.getName())); + if (hasMatch(searchTerm, list.toArray(new String[list.size()]))) + modList.add(mod); + } + this.modList = new LinkedList<>(modList); + int i = -1; + for(int j = 0; j < modList.size(); j++) { + ModInfo mod = modList.get(j); + if (mod.id.equals(currentId)) + i = j; + } + setCurrentIndex(i); + } + + private boolean hasMatch(String searchTerm, String... items) { + for(String i : items) + if (i.toLowerCase().contains(searchTerm.toLowerCase())) + return true; + return false; + } + +} diff --git a/src/main/java/org/dimdev/rift/modlist/GuiModsView.java b/src/main/java/org/dimdev/rift/modlist/GuiModsView.java new file mode 100644 index 0000000..a2eca67 --- /dev/null +++ b/src/main/java/org/dimdev/rift/modlist/GuiModsView.java @@ -0,0 +1,132 @@ +package org.dimdev.rift.modlist; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.Util; +import org.dimdev.riftloader.ModInfo; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +public class GuiModsView extends GuiScreen { + + private ModInfo mod; + + public GuiModsView(ModInfo mod) { + this.mod = mod; + } + + @Override + protected void initGui() { + if (mod.url != null) { + addButton(new GuiButton(601, this.width - 80, 20, 70, 20, I18n.format("rift.modlist.visit_website")) { + @Override + public void onClick(double mouseX, double mouseY) { + super.onClick(mouseX, mouseY); + try { + Util.getOSType().openURL(new URL(mod.url)); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + }); + } + } + + @Override + public void render(int mouseX, int mouseY, float partialTicks) { + this.overlayBackground(0, 52, 64, 64, 64, 255, 255); + Minecraft.getInstance().getTextureManager().bindTexture(ModList.getModIcon(mod.id, mod.source)); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + Gui.drawModalRectWithCustomSizedTexture(10, 10, 0, 0, 32, 32, 32, 32); + + //Draw Dark thing + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + this.overlayBackground(52, this.height, 32, 32, 32, 255, 255); + + //Draw Shade + GlStateManager.enableBlend(); + GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE); + GlStateManager.disableAlphaTest(); + GlStateManager.shadeModel(7425); + GlStateManager.disableTexture2D(); + bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); + bufferbuilder.pos(0, 52D + 4, 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 0).endVertex(); + bufferbuilder.pos(this.width, 52D + 4, 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 0).endVertex(); + bufferbuilder.pos(this.width, 52D, 0.0D).tex(1.0D, 0.0D).color(0, 0, 0, 255).endVertex(); + bufferbuilder.pos(0, 52D, 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex(); + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.shadeModel(7424); + GlStateManager.enableAlphaTest(); + GlStateManager.disableBlend(); + + //Render info + String modName = mod.name != null ? mod.name : mod.id; + int j1 = fontRenderer.getStringWidth(modName); + if (j1 > this.width - 48 - 90) + modName = fontRenderer.trimStringToWidth(modName, this.width - 48 - 90 - 3) + "..."; + this.fontRenderer.drawStringWithShadow(modName, 48, 11, 16777215); + String versions = I18n.format("rift.modlist.versions", (mod.version != null ? mod.version : "Unidentified")); + j1 = fontRenderer.getStringWidth(versions); + if (j1 > this.width - 48 - 90) + versions = fontRenderer.trimStringToWidth(versions, this.width - 48 - 90 - 3) + "..."; + this.fontRenderer.drawStringWithShadow(versions, 48, 21, 8421504); + if (mod.url != null) { + String url = I18n.format("rift.modlist.url", (mod.url != null ? mod.url : "Unidentified")); + j1 = fontRenderer.getStringWidth(url); + if (j1 > this.width - 48 - 90) + url = fontRenderer.trimStringToWidth(url, this.width - 48 - 90 - 3) + "..."; + this.fontRenderer.drawStringWithShadow(url, 48, 31, 8421504); + } + String id = I18n.format("rift.modlist.id", mod.id); + j1 = fontRenderer.getStringWidth(id); + if (j1 > this.width - 48 * 2) + id = fontRenderer.trimStringToWidth(id, this.width - 48 * 2 - 3) + "..."; + this.fontRenderer.drawStringWithShadow(id, 48, (float) (60), 8421504); + String description = mod.description != null ? mod.description : ""; + List list = this.mc.fontRenderer.listFormattedStringToWidth(description, this.width - 48 * 2); + for(int i1 = 0; i1 < list.size(); ++i1) + this.fontRenderer.drawStringWithShadow(list.get(i1), 48, (float) (75 + 10 * i1), 16777215); + + super.render(mouseX, mouseY, partialTicks); + } + + /** + * Overlays the background to hide scrolled items + */ + protected void overlayBackground(int startY, int endY, int red, int green, int blue, int startAlpha, int endAlpha) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + this.mc.getTextureManager().bindTexture(Gui.OPTIONS_BACKGROUND); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + float f = 32.0F; + bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); + bufferbuilder.pos((double) 0, (double) endY, 0.0D).tex(0.0D, (double) ((float) endY / 32.0F)).color(red, green, blue, endAlpha).endVertex(); + bufferbuilder.pos((double) (0 + this.width), (double) endY, 0.0D).tex((double) ((float) this.width / 32.0F), (double) ((float) endY / 32.0F)).color(red, green, blue, endAlpha).endVertex(); + bufferbuilder.pos((double) (0 + this.width), (double) startY, 0.0D).tex((double) ((float) this.width / 32.0F), (double) ((float) startY / 32.0F)).color(red, green, blue, startAlpha).endVertex(); + bufferbuilder.pos((double) 0, (double) startY, 0.0D).tex(0.0D, (double) ((float) startY / 32.0F)).color(red, green, blue, startAlpha).endVertex(); + tessellator.draw(); + } + + @Override + public boolean keyPressed(int p_keyPressed_1_, int p_keyPressed_2_, int p_keyPressed_3_) { + if (p_keyPressed_1_ == 256 && this.allowCloseWithEscape()) { + this.close(); + this.mc.displayGuiScreen(ModList.guiModsList); + return true; + } else { + return super.keyPressed(p_keyPressed_1_, p_keyPressed_2_, p_keyPressed_3_); + } + } + +} diff --git a/src/main/java/org/dimdev/rift/modlist/ModList.java b/src/main/java/org/dimdev/rift/modlist/ModList.java new file mode 100644 index 0000000..a595f4e --- /dev/null +++ b/src/main/java/org/dimdev/rift/modlist/ModList.java @@ -0,0 +1,48 @@ +package org.dimdev.rift.modlist; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.texture.NativeImage; +import net.minecraft.util.ResourceLocation; + +import java.io.File; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class ModList { + + static GuiMods guiModsList; + private static Map modIconMap = new HashMap<>(); + private static final ResourceLocation packIcon = new ResourceLocation("textures/misc/unknown_pack.png"); + + public static void displayModList() { + if (guiModsList == null) + guiModsList = new GuiMods(); + else + guiModsList.getGuiModListContent().setCurrentIndex(-1); + guiModsList.previousGui = Minecraft.getInstance().currentScreen; + guiModsList.reloadSearch(); + Minecraft.getInstance().displayGuiScreen(guiModsList); + } + + public static ResourceLocation getModIcon(String modid, File source) { + if (modIconMap.containsKey(modid)) + return modIconMap.get(modid); + if (!source.isFile()) return packIcon; + try (JarFile jar = new JarFile(source)) { + JarEntry entry = jar.getJarEntry("pack.png"); + if (entry != null) { + InputStream inputStream = jar.getInputStream(entry); + NativeImage nativeImage = NativeImage.read(inputStream); + return Minecraft.getInstance().getTextureManager().getDynamicTextureLocation("modpackicon", new DynamicTexture(nativeImage)); + } + } catch (Exception e) { + e.printStackTrace(); + } + return packIcon; + } + +} diff --git a/src/main/java/org/dimdev/riftloader/ModInfo.java b/src/main/java/org/dimdev/riftloader/ModInfo.java index 29ac3ab..b81ddcb 100644 --- a/src/main/java/org/dimdev/riftloader/ModInfo.java +++ b/src/main/java/org/dimdev/riftloader/ModInfo.java @@ -43,6 +43,9 @@ public Listener(String className) { public String id; public String name; + public String description; + public String version; + public String url; public List authors = new ArrayList<>(); public List listeners = new ArrayList<>(); } diff --git a/src/main/resources/assets/rift/lang/en_us.json b/src/main/resources/assets/rift/lang/en_us.json new file mode 100644 index 0000000..3ac630e --- /dev/null +++ b/src/main/resources/assets/rift/lang/en_us.json @@ -0,0 +1,12 @@ +{ + "rift.modlist.mods": "Mods List", + "rift.modlist.openFolder": "Open Mods Folder", + "rift.modlist.authors": "By", + "rift.modlist.noone": "No One", + "rift.modlist.view": "View", + "rift.modlist.done": "Done", + "rift.modlist.search_mods": "Search Mods...", + "rift.modlist.versions": "Version: %s", + "rift.modlist.url": "Website: %s", + "rift.modlist.id": "Mod ID: %s" +} \ No newline at end of file diff --git a/src/main/resources/mixins.rift.core.json b/src/main/resources/mixins.rift.core.json index b67cf7e..ff2e380 100644 --- a/src/main/resources/mixins.rift.core.json +++ b/src/main/resources/mixins.rift.core.json @@ -13,6 +13,7 @@ "client.MixinLayerArmorBase", "client.MixinWaterFluid", "client.MixinLavaFluid", - "client.MixinItemRenderer" + "client.MixinItemRenderer", + "client.MixinMainMenu" ] } diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..2f1f3e9 --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 4, + "description": "Rift" + } +} \ No newline at end of file diff --git a/src/main/resources/pack.png b/src/main/resources/pack.png new file mode 100644 index 0000000..6064095 Binary files /dev/null and b/src/main/resources/pack.png differ diff --git a/src/main/resources/riftmod.json b/src/main/resources/riftmod.json index 5f5716c..46da3a5 100644 --- a/src/main/resources/riftmod.json +++ b/src/main/resources/riftmod.json @@ -4,6 +4,7 @@ "authors": [ "Runemoro" ], + "version": "${version}", "listeners": [ { "class": "org.dimdev.rift.Rift",