Browse Source

skill xp display

Kajetan Johannes Hammerle 3 years ago
parent
commit
26a46cc3e6
4 changed files with 331 additions and 60 deletions
  1. 1 0
      .gitignore
  2. 2 2
      build.gradle
  3. 235 58
      src/main/java/me/hammerle/HeK.java
  4. 93 0
      src/main/java/me/hammerle/Skill.java

+ 1 - 0
.gitignore

@@ -5,3 +5,4 @@
 gradle.properties
 gradlew
 /.gradle
+buildAndMove.sh

+ 2 - 2
build.gradle

@@ -12,8 +12,8 @@ apply plugin: 'net.minecraftforge.gradle'
 // Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
 
 version = '1.0'
-group = 'me.hammerle.hefix'
-archivesBaseName = 'hefix'
+group = 'me.hammerle.hek'
+archivesBaseName = 'hek'
 
 minecraft {
     mappings channel: 'snapshot', version: '20200514-1.15.1'

+ 235 - 58
src/main/java/me/hammerle/HeK.java

@@ -1,99 +1,276 @@
 package me.hammerle;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
 import java.util.Arrays;
-import net.minecraft.block.Block;
-import net.minecraft.block.Blocks;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.AbstractGui;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.util.ITooltipFlag.TooltipFlags;
+import net.minecraft.item.ItemStack;
 import net.minecraft.util.text.ChatType;
+import net.minecraft.util.text.ITextComponent;
 import net.minecraft.util.text.StringTextComponent;
+import net.minecraftforge.client.event.GuiContainerEvent;
 import net.minecraftforge.client.event.ClientChatEvent;
 import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.event.TickEvent;
 import net.minecraftforge.eventbus.api.SubscribeEvent;
 import net.minecraftforge.fml.common.Mod;
 
 @Mod.EventBusSubscriber
-@Mod("hefix")
+@Mod("hek")
 public class HeK {
 
+    private final static HashMap<String, Skill> SKILLS = new HashMap<>();
+
+    private static void addSkill(String name) {
+        SKILLS.put(name, new Skill(name));
+    }
+
+    private static int skillCorner = 0;
+    private static boolean toggle = true;
+
+    static {
+        addSkill("Attack");
+        addSkill("Constitution");
+        addSkill("Mining");
+        addSkill("Smelting");
+        addSkill("Fishing");
+        addSkill("Hunting");
+        addSkill("Taming");
+        addSkill("Leatherworking");
+        addSkill("Tailoring");
+        addSkill("Strength");
+        addSkill("Woodcutting");
+        addSkill("Firemaking");
+        addSkill("Weaponsmithing");
+        addSkill("Farming");
+        addSkill("Cooking");
+        addSkill("Merchanting");
+        addSkill("Crafting");
+        addSkill("Tinkering");
+        addSkill("Ranged");
+        addSkill("Fletching");
+        addSkill("Carpentry");
+        addSkill("Armoursmithing");
+        addSkill("Herblore");
+        addSkill("Agility");
+        addSkill("Thieving");
+        addSkill("Forgery");
+        addSkill("Alchemy");
+        addSkill("Defence");
+
+        load();
+    }
+
     private static String filter = "Hegemony";
-    private static String percent = null;
-    private static double startExp = 0.0;
-    private static double exp = 0.0;
-    private static double nextExp = 0.0;
 
     private static void sendMessage(String msg) {
         Minecraft.getInstance().ingameGUI.addChatMessage(ChatType.CHAT, new StringTextComponent(msg));
     }
 
-    private static boolean isOre(Block b) {
-        return b == Blocks.IRON_ORE || b == Blocks.COAL_ORE;
+    private static String removeFormatting(ITextComponent text) {
+        return text.getFormattedText().replaceAll("§.", "");
+    }
+
+    private static double parse(String number) {
+        try {
+            return Double.parseDouble(number.replace(",", ""));
+        } catch(NumberFormatException ex) {
+            return 0.0;
+        }
+    }
+
+    private static void save() {
+        File config = new File("./config");
+        if(!config.exists()) {
+            config.mkdir();
+        }
+        ArrayList<String> data = new ArrayList<>();
+        data.add(String.valueOf(skillCorner));
+        try {
+            Files.write(new File("./config/hek").toPath(), data);
+        } catch(IOException ex) {
+        }
+    }
+
+    private static void load() {
+        try {
+            File config = new File("./config/hek");
+            if(!config.exists()) {
+                return;
+            }
+
+            List<String> list = Files.readAllLines(config.toPath());
+            if(list.isEmpty()) {
+                return;
+            }
+            try {
+                skillCorner = Integer.parseInt(list.get(0));
+            } catch(NumberFormatException ex) {
+            }
+        } catch(Exception ex) {
+        }
     }
 
     @SubscribeEvent
-    public static void onClientChat(ClientChatEvent e) {
-        if(!e.getMessage().startsWith("/")) {
+    public static void onClientChat(GuiContainerEvent e) {
+        if(!e.getGuiContainer().getTitle().getFormattedText().contains("Skills")) {
             return;
         }
-        String[] parts = e.getMessage().split(" ");
-        switch(parts[0]) {
-            case "/hefix":
-                e.setCanceled(true);
-                if(parts.length < 2) {
-                    filter = null;
-                    sendMessage("Filter cleared");
-                    return;
-                }
-                filter = String.join(" ", Arrays.copyOfRange(parts, 1, parts.length));
-                sendMessage("Filter set to '" + filter + "'");
-                break;
-            case "/percent":
-                e.setCanceled(true);
-                if(parts.length < 4) {
-                    percent = null;
-                    sendMessage("EXP cleared");
-                    return;
-                }
-                percent = parts[1];
-                try {
-                    exp = Double.parseDouble(parts[2]);
-                    startExp = exp;
-                    nextExp = Double.parseDouble(parts[3]);
-                } catch(NumberFormatException ex) {
-                    sendMessage("Type valid numbers");
-                    return;
+        for(ItemStack stack : e.getGuiContainer().getContainer().getInventory()) {
+            if(stack.isEmpty()) {
+                continue;
+            }
+            String name = removeFormatting(stack.getDisplayName());
+            Skill skill = SKILLS.get(name);
+            if(skill == null) {
+                continue;
+            }
+            List<ITextComponent> lore = stack.getTooltip(Minecraft.getInstance().player, TooltipFlags.NORMAL);
+            for(ITextComponent text : lore) {
+                String line = removeFormatting(text);
+                if(line.startsWith("Experience") && line.length() >= 13) {
+                    skill.setExperience(parse(line.substring(12)));
                 }
-                sendMessage(String.format("Percent set to '%s' and %.1f and %.1f", percent, exp, nextExp));
-                break;
+            }
         }
+    }
 
+    @SubscribeEvent
+    public static void onClientChat(ClientChatEvent e) {
+        try {
+            if(!e.getMessage().startsWith("/")) {
+                return;
+            }
+            String[] parts = e.getMessage().split(" ");
+            switch(parts[0]) {
+                case "/hefix":
+                    e.setCanceled(true);
+                    if(parts.length < 2) {
+                        filter = null;
+                        sendMessage("Filter cleared");
+                        return;
+                    }
+                    filter = String.join(" ", Arrays.copyOfRange(parts, 1, parts.length));
+                    sendMessage("Filter set to '" + filter + "'");
+                    break;
+                case "/toggle":
+                    e.setCanceled(true);
+                    skillCorner = (skillCorner + 1) % 4;
+                    save();
+                    break;
+            }
+        } catch(Exception ex) {
+        }
     }
 
     @SubscribeEvent
     public static void onChatReceive(ClientChatReceivedEvent e) {
-        String msg = e.getMessage().getFormattedText();
+        String msg = removeFormatting(e.getMessage());
         if(filter != null && msg.contains(filter)) {
             e.setCanceled(true);
         }
-        if(percent != null && e.getType() == ChatType.GAME_INFO && msg.contains(percent)) {
-            msg = msg.replaceAll("§.", "");
+        if(e.getType() == ChatType.GAME_INFO) {
             String[] parts = msg.split(" ");
-            for(int i = 0; i < parts.length; i++) {
-                if(parts[i].equals(percent)) {
-                    if(i == 0) {
-                        continue;
-                    }
-                    try {
-                        exp += Double.parseDouble(parts[i - 1]);
-                        double d = ((exp - startExp) * 100.0) / (nextExp - startExp);
-                        e.setMessage(new StringTextComponent(String.format("§6%s§r +%s - %.1f%%", percent, parts[i - 1], d)));
-                        return;
-                    } catch(NumberFormatException ex) {
-                        e.setMessage(new StringTextComponent(ex.getLocalizedMessage()));
-                        break;
-                    }
+            ArrayList<Skill> skills = new ArrayList<>();
+            ArrayList<Double> xp = new ArrayList<>();
+            for(String part : parts) {
+                part = part.replace(",", "");
+                Skill skill = SKILLS.get(part);
+                if(skill != null) {
+                    skills.add(skill);
+                    continue;
+                }
+                try {
+                    xp.add(Double.parseDouble(part));
+                } catch(NumberFormatException ex) {
                 }
             }
-            e.setCanceled(true);
+            if(skills.size() == xp.size()) {
+                for(int i = 0; i < skills.size(); i++) {
+                    skills.get(i).addExperience(xp.get(i));
+                }
+            } else if(xp.size() == 1) {
+                for(int i = 0; i < skills.size(); i++) {
+                    skills.get(i).addExperience(xp.get(0));
+                }
+            }
+        }
+    }
+
+    @SubscribeEvent
+    public static void onClientTick(TickEvent.ClientTickEvent e) {
+        if(e.phase == TickEvent.Phase.END) {
+            SKILLS.values().forEach(skill -> skill.tick());
+        }
+    }
+
+    @SubscribeEvent
+    public static void onRenderGui(RenderGameOverlayEvent.Post e) {
+        if(e.getType() != RenderGameOverlayEvent.ElementType.EXPERIENCE) {
+            return;
+        }
+        toggle = false;
+        List<String> texts = SKILLS.values().stream()
+                .filter(skill -> skill.shouldRender())
+                .sorted()
+                .map(skill -> {
+                    String c = "§r";
+                    if(toggle) {
+                        c = "§7";
+                    }
+                    toggle = !toggle;
+                    if(skill.shouldRenderLastPercent()) {
+                        return String.format("§6Lv. %s%d §6%s: %s%.2f%% +%.2f%%",
+                                c, skill.getLevel(), skill.getName(), c, skill.getPercent(), skill.getLastPercent());
+                    }
+                    return String.format("§6Lv. %s%d §6%s: %s%.2f%%",
+                            c, skill.getLevel(), skill.getName(), c, skill.getPercent());
+                })
+                .collect(Collectors.toList());
+
+        Minecraft mc = Minecraft.getInstance();
+        FontRenderer fr = mc.fontRenderer;
+        int width = 0;
+        int height = 4;
+        for(String text : texts) {
+            height += fr.FONT_HEIGHT;
+            width = Math.max(fr.getStringWidth(text), width);
+        }
+        width += 4;
+
+        // 0 - top left
+        int y = 0;
+        int x = 0;
+        switch(skillCorner) {
+            case 1: // 1 - top right
+                x = mc.getMainWindow().getScaledWidth() - width;
+                y = 0;
+                break;
+            case 2: // 2 - bottom left
+                x = 0;
+                y = mc.getMainWindow().getScaledHeight() - height;
+                break;
+            case 3: // 3 - bottom right
+                x = mc.getMainWindow().getScaledWidth() - width;
+                y = mc.getMainWindow().getScaledHeight() - height;
+                break;
+        }
+
+        AbstractGui.fill(x, y, x + width, y + height, 1342177280);
+        x += 2;
+        y += 2;
+        for(String text : texts) {
+            fr.drawString(text, x, y, 0xFFFFFF);
+            y += fr.FONT_HEIGHT;
         }
     }
 }

+ 93 - 0
src/main/java/me/hammerle/Skill.java

@@ -0,0 +1,93 @@
+package me.hammerle;
+
+public class Skill implements Comparable<Skill> {
+
+    private final static double[] xpForLevel = new double[]{
+        0, 83, 176, 279, 392, 518, 656, 810, 979, 1166,
+        1372, 1599, 1851, 2128, 2435, 2773, 3146, 3558, 4012, 4514,
+        5068, 5680, 6353, 7098, 7920, 8827, 9827, 10932, 12151, 13496,
+        14981, 16620, 18429, 20426, 22630, 25063, 27747, 30712, 33984, 37596,
+        41582, 45984, 50842, 56205, 62127, 68662, 75878, 83844, 92638, 102346,
+        113064, 124896, 137959, 152380, 168302, 185880, 205286, 226710, 250384, 276479,
+        305310, 337142, 372285, 411085, 453922, 501216, 553432, 611082, 674731, 745003,
+        822589, 908249, 1002824, 1107241, 1222525, 1349807, 1490337, 1645492, 1816796, 1975629,
+        2214746
+    };
+
+    private final String name;
+    private int level = 1;
+    private double xp = 0;
+    private int ticks;
+    private int lastTicks = 0;
+    private double last = 0.0;
+
+    public Skill(String name) {
+        this.name = name;
+    }
+
+    public void setExperience(double xp) {
+        this.xp = xp;
+        level = 1;
+        while(level < xpForLevel.length && this.xp >= xpForLevel[level]) {
+            level++;
+        }
+    }
+
+    public void addExperience(double xp) {
+        lastTicks = 20 * 15;
+        last = xp;
+        this.xp += xp;
+        while(level < xpForLevel.length && this.xp >= xpForLevel[level]) {
+            level++;
+        }
+        ticks = 20 * 60;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public double getExperience() {
+        return xp;
+    }
+
+    public double getExperienceForLevel() {
+        return xpForLevel[level];
+    }
+
+    public double getPercent() {
+        return (100.0 * (xp - xpForLevel[level - 1])) / (xpForLevel[level] - xpForLevel[level - 1]);
+    }
+
+    public double getLastPercent() {
+        return (100.0 * last) / (xpForLevel[level] - xpForLevel[level - 1]);
+    }
+
+    public void tick() {
+        if(ticks > 0) {
+            ticks--;
+        }
+        if(lastTicks > 0) {
+            lastTicks--;
+        } else {
+            last = 0.0f;
+        }
+    }
+
+    public boolean shouldRender() {
+        return ticks > 0;
+    }
+
+    public boolean shouldRenderLastPercent() {
+        return lastTicks > 0;
+    }
+
+    @Override
+    public int compareTo(Skill other) {
+        return -Integer.compare(ticks, other.ticks);
+    }
+
+    public int getLevel() {
+        return level;
+    }
+}