From 309f555533056eb008631305c2f2b10126ac1d98 Mon Sep 17 00:00:00 2001 From: Tyoda Date: Sun, 15 Oct 2023 20:52:34 +0200 Subject: [PATCH 1/2] reload status effects library in ModPacks.reloadPacks() --- .../modsupport/packs/ModPacks.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java b/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java index cb0d413..d42b9a5 100644 --- a/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java +++ b/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java @@ -16,6 +16,9 @@ import java.util.logging.Level; import java.util.logging.Logger; +import com.wurmonline.client.renderer.gui.HeadsUpDisplay; +import com.wurmonline.client.renderer.gui.StatusEffect.StatusEffectXmlParser; +import com.wurmonline.client.renderer.gui.StatusEffectComponent; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; @@ -283,6 +286,7 @@ private static void reloadPacks() throws IllegalArgumentException, IllegalAccess resolved.clear(); boolean reloadIcons = false; + boolean reloadStatusEffects = false; for (java.util.Map.Entry entry : oldResolved.entrySet()) { ResourceUrl oldUrl = entry.getValue(); @@ -292,6 +296,8 @@ private static void reloadPacks() throws IllegalArgumentException, IllegalAccess if (Arrays.asList(IconConstants.ICON_SHEET_FILE_NAMES).contains(entry.getKey())) { reloadIcons = true; + } else if ("buff.xml".equals(entry.getKey())) { + reloadStatusEffects = true; } else { ResourceTextureLoader.reload(oldUrl, newUrl); } @@ -302,6 +308,18 @@ private static void reloadPacks() throws IllegalArgumentException, IllegalAccess IconLoader.initIcons(); IconLoader.clear(); } + + if (reloadStatusEffects) { + try { + final WurmClientBase clientBase = ReflectionUtil.getPrivateField(WurmClientBase.class, ReflectionUtil.getField(WurmClientBase.class, "clientObject")); + final HeadsUpDisplay hud = ReflectionUtil.getPrivateField(clientBase, ReflectionUtil.getField(WurmClientBase.class, "hud")); + Object statusEffectLibrary = StatusEffectXmlParser.loadXml(); + ReflectionUtil.setPrivateField(hud.getStatusEffectComponent(), ReflectionUtil.getField(StatusEffectComponent.class, "statusEffectLibrary"), statusEffectLibrary); + } catch (NoSuchFieldException e) { + logger.log(Level.SEVERE, e.getMessage(), e); + throw new HookException(e); + } + } } private static void updateServerData(Object jarPack, Set options) { From 22707ffea54c11caec7e974ad7ca1cc26fc33a43 Mon Sep 17 00:00:00 2001 From: Tyoda Date: Sun, 15 Oct 2023 23:20:53 +0200 Subject: [PATCH 2/2] allow sending modded status effects before the server pack is loaded --- .../modsupport/packs/ModPacks.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java b/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java index d42b9a5..4dc7936 100644 --- a/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java +++ b/modules/modlauncher/src/main/java/org/gotti/wurmunlimited/modsupport/packs/ModPacks.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -103,6 +104,8 @@ public enum Options { // Track JarPacks created for a absolute pack file locations private static HashMap addedPacks = new HashMap<>(); + private static final ArrayList failedStatusEffects = new ArrayList<>(); + public static void preInit() { try { // com.wurmonline.client.resources.textures.PlayerTextureBuilder.loadImage(ResourceUrl, String) @@ -125,7 +128,17 @@ public void edit(MethodCall m) throws CannotCompileException { classPool.get("com.wurmonline.client.resources.textures.PlayerTextureBuilderGL").getMethod("generateTexture", Descriptor.ofMethod(CtPrimitiveType.voidType, new CtClass[0])).instrument(modArmorDeriveEditor); classPool.get("com.wurmonline.client.renderer.cell.PlayerTexture$PlayerBodyTextureLoader").getMethod("run", Descriptor.ofMethod(CtPrimitiveType.voidType, new CtClass[0])).instrument(modArmorDeriveEditor); - + + classPool.get("com.wurmonline.client.renderer.gui.StatusEffectComponent") + .getMethod("addStatusEffect", Descriptor.ofMethod(CtPrimitiveType.voidType, new CtClass[]{CtPrimitiveType.longType, CtPrimitiveType.intType, CtPrimitiveType.intType, classPool.get("java.lang.String")})) + .instrument(new ExprEditor(){ + @Override + public void edit(MethodCall m) throws CannotCompileException { + if(m.getMethodName().equals("updateSize")) { + m.replace("$_ = $proceed($$); if(info==null) org.gotti.wurmunlimited.modsupport.packs.ModPacks.addFailedStatusEffect(id, typeId, duration, name);"); + } + } + }); } catch (NotFoundException | CannotCompileException e) { throw new HookException(e); } @@ -315,6 +328,17 @@ private static void reloadPacks() throws IllegalArgumentException, IllegalAccess final HeadsUpDisplay hud = ReflectionUtil.getPrivateField(clientBase, ReflectionUtil.getField(WurmClientBase.class, "hud")); Object statusEffectLibrary = StatusEffectXmlParser.loadXml(); ReflectionUtil.setPrivateField(hud.getStatusEffectComponent(), ReflectionUtil.getField(StatusEffectComponent.class, "statusEffectLibrary"), statusEffectLibrary); + + // will send this many effects, since addStatusEffect might modify failedStatusEffects + final int numEffects = failedStatusEffects.size(); + for (int i = 0; i < numEffects; ++i) { + FailedStatusEffect fSE = failedStatusEffects.remove(0); + + int remainingDuration = (int)(fSE.sentAtSeconds + fSE.duration - System.currentTimeMillis()/1000); + if (remainingDuration > 0) { + hud.getStatusEffectComponent().addStatusEffect(fSE.id, fSE.typeId, remainingDuration, fSE.name); + } + } } catch (NoSuchFieldException e) { logger.log(Level.SEVERE, e.getMessage(), e); throw new HookException(e); @@ -379,4 +403,23 @@ public static void refreshPlayerModels() { } } + public static void addFailedStatusEffect(final long id, final int typeId, final int duration, final String name) { + failedStatusEffects.add(new FailedStatusEffect(System.currentTimeMillis()/1000, id, typeId, duration, name)); + } + + private static class FailedStatusEffect { + public final long sentAtSeconds; + public final long id; + public final int typeId; + public final int duration; + public final String name; + + public FailedStatusEffect(final long sentAtSeconds, final long id, final int typeId, final int duration, final String name) { + this.sentAtSeconds = sentAtSeconds; + this.id = id; + this.typeId = typeId; + this.duration = duration; + this.name = name; + } + } }