Created
May 24, 2017 21:42
-
-
Save Joedobo27/089c17c7f691f6d6ffb03577ad042ed8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.joedobo27.simplefoodbonuses; | |
import javassist.*; | |
import javassist.bytecode.Descriptor; | |
import javassist.expr.ExprEditor; | |
import javassist.expr.MethodCall; | |
import org.gotti.wurmunlimited.modloader.classhooks.HookManager; | |
import org.gotti.wurmunlimited.modloader.interfaces.Configurable; | |
import org.gotti.wurmunlimited.modloader.interfaces.PreInitable; | |
import org.gotti.wurmunlimited.modloader.interfaces.WurmServerMod; | |
import java.util.Arrays; | |
import java.util.Objects; | |
import java.util.Properties; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
public class SimpleFoodBonusesMod implements WurmServerMod, PreInitable, Configurable{ | |
static final Logger logger = Logger.getLogger(SimpleFoodBonusesMod.class.getName()); | |
private static boolean versionCompliant = false; | |
private static final String[] STEAM_VERSION = new String[]{"1.3.1.3"}; | |
@Override | |
public void configure(Properties properties) { | |
if (Arrays.stream(STEAM_VERSION) | |
.filter(s -> Objects.equals(s, properties.getProperty("steamVersion", null))) | |
.count() > 0) | |
versionCompliant = true; | |
else | |
logger.log(Level.WARNING, "WU version mismatch. Your " + properties.getProperty(" steamVersion", null) | |
+ "version doesn't match one of BulkOptionsMod's required versions " + Arrays.toString(STEAM_VERSION)); | |
} | |
@Override | |
public void preInit() { | |
if (!versionCompliant) | |
return; | |
int[] successes = new int[6]; | |
int[] result; | |
result = modifyHungerBytecodeChange(); | |
System.arraycopy(result,0, successes, 0, 1); | |
result = drinkBytecodeChange(); | |
System.arraycopy(result,0, successes, 1, 2); | |
result = addTimedAffinityFromBonusBytecodeChange(); | |
System.arraycopy(result,0, successes, 3, 1); | |
result = eatBytecodeChange(); | |
System.arraycopy(result,0, successes, 4, 1); | |
result = alterSkillBytecodeChange(); | |
System.arraycopy(result,0, successes, 5, 1); | |
evaluateChangesArray(successes); | |
} | |
/** | |
* edit Skill.alterSkill() so nutritional bonus is 0 to 15% instead of 0 to 5%. Instead of a complicated affinity system | |
* just add up to 10% more bonus from nutrition level. | |
* was- | |
* staminaMod += Math.max(player2.getStatus().getNutritionlevel() / 10.0f - 0.05f, 0.0f); | |
* becomes- | |
* staminaMod += Math.max(player2.getStatus().getNutritionlevel() * 5 / 33, 0.0f); | |
* | |
* note, 0.99 nutrition needs to be 0.15 bonus. 0.15 / 0.99 is repeating .15 or 5/33. thus, multipliing by 5/33 will | |
* make generate a value from 0 to 15%. | |
*/ | |
private int[] alterSkillBytecodeChange() { | |
final int[] successes = {0}; | |
try { | |
CtClass skillCt = HookManager.getInstance().getClassPool().get("com.wurmonline.server.skills.Skill"); | |
CtClass returnType = CtPrimitiveType.voidType; | |
CtClass[] params = { | |
CtPrimitiveType.doubleType, CtPrimitiveType.booleanType, CtPrimitiveType.floatType, CtPrimitiveType.booleanType, | |
CtPrimitiveType.doubleType | |
}; | |
CtMethod alterSkillCt = skillCt.getDeclaredMethod("alterSkill", params); | |
alterSkillCt.instrument(new ExprEditor() { | |
@Override | |
public void edit(MethodCall methodCall) throws CannotCompileException { | |
if (Objects.equals(methodCall.getMethodName(), "max") && methodCall.getLineNumber() == 1556) { | |
methodCall.replace("{ $1 = player.getStatus().getNutritionlevel() * 5 / 33; $_ = $proceed($$); }"); | |
successes[0] = 1; | |
} | |
} | |
}); | |
}catch (NotFoundException | CannotCompileException e) { | |
logger.warning(e.getMessage()); | |
} | |
return successes; | |
} | |
/** | |
* edit MethodsItems.eat() so food is never too hot to eat. | |
* By preventing getTemperature from returning values greater then 2500 food is never too hot. | |
*/ | |
private int[] eatBytecodeChange() { | |
final int[] successes = {0}; | |
try { | |
CtClass methodItemsCt = HookManager.getInstance().getClassPool().get("com.wurmonline.server.behaviours.MethodsItems"); | |
CtClass[] params = { | |
HookManager.getInstance().getClassPool().get("com.wurmonline.server.behaviours.Action"), | |
HookManager.getInstance().getClassPool().get("com.wurmonline.server.creatures.Creature"), | |
HookManager.getInstance().getClassPool().get("com.wurmonline.server.items.Item"), | |
CtPrimitiveType.floatType | |
}; | |
CtMethod eatCt = methodItemsCt.getDeclaredMethod("eat", params); | |
eatCt.instrument(new ExprEditor() { | |
@Override | |
public void edit(MethodCall methodCall) throws CannotCompileException { | |
if (Objects.equals(methodCall.getMethodName(), "getTemperature")) { | |
methodCall.replace("$_ = $_ > 2500 ? 2500 : $_;"); | |
successes[0] = 1; | |
} | |
} | |
}); | |
}catch (NotFoundException | CannotCompileException e) { | |
logger.warning(e.getMessage()); | |
} | |
return successes; | |
} | |
/** | |
* edit AffinitiesTimed.addTimedAffinityFromBonus() to make it so getBonus() returns -1 and disables affinity creation. | |
* | |
* was- | |
* final int ibonus = item.getBonus(); | |
* becomes- | |
* final int ibonus = -1; | |
*/ | |
private int[] addTimedAffinityFromBonusBytecodeChange() { | |
final int[] successes = {0}; | |
try { | |
CtClass AffinitiesTimedCt = HookManager.getInstance().getClassPool().get("com.wurmonline.server.skills.AffinitiesTimed"); | |
CtClass returnType = CtPrimitiveType.voidType; | |
CtClass[] paramTypes = { | |
HookManager.getInstance().getClassPool().get("com.wurmonline.server.creatures.Creature"), | |
CtPrimitiveType.intType, | |
HookManager.getInstance().getClassPool().get("com.wurmonline.server.items.Item") | |
}; | |
CtMethod addTimedAffinityFromBonusCt = AffinitiesTimedCt.getMethod("addTimedAffinityFromBonus", Descriptor.ofMethod(returnType, paramTypes)); | |
addTimedAffinityFromBonusCt.instrument(new ExprEditor() { | |
@Override | |
public void edit(MethodCall methodCall) throws CannotCompileException { | |
if (Objects.equals(methodCall.getMethodName(), "getBonus")) { | |
methodCall.replace("$_ = -1;"); | |
successes[0] = 1; | |
} | |
} | |
}); | |
}catch (NotFoundException | CannotCompileException e) { | |
logger.warning(e.getMessage()); | |
} | |
return successes; | |
} | |
/** | |
* edit MethodsItems.modifyHunger() so food complexity has no effect. | |
* was- | |
* float complexity = food.getFoodComplexity() * 50.0f; | |
* becomes- | |
* float complexity = 2.0f * 50.0f; | |
* getFoodComplexity() would return 2 if the food had 10 stages and 30 ingredients which would be one of the most | |
* complex or difficult meals. | |
*/ | |
private int[] modifyHungerBytecodeChange() { | |
final int[] successes = {0}; | |
try { | |
CtClass methodItemsCt = HookManager.getInstance().getClassPool().get("com.wurmonline.server.behaviours.MethodsItems"); | |
CtMethod modifyHungerCt = methodItemsCt.getDeclaredMethod("modifyHunger"); | |
modifyHungerCt.instrument(new ExprEditor() { | |
@Override | |
public void edit(MethodCall methodCall) throws CannotCompileException { | |
if (Objects.equals(methodCall.getMethodName(), "getFoodComplexity")) { | |
methodCall.replace("$_ = 2.0;"); | |
successes[0] = 1; | |
} | |
} | |
}); | |
}catch (NotFoundException | CannotCompileException e) { | |
logger.warning(e.getMessage()); | |
} | |
return successes; | |
} | |
/** | |
* edit MethodsItems.drink() so food complexity has no effect. | |
* was- | |
* final float complexity = drink.getFoodComplexity() * 20.0f; | |
* becomes- | |
* float complexity = 2.0f * 20.0f; | |
* getFoodComplexity() would return 2 if the drink had 10 stages and 30 ingredients which would be one of the most | |
* complex or difficult drinks. | |
* | |
* edit MethodsItems.drink() so drinks are never too hot to drink. | |
* By making sure getTemperature returns values less then 300 drinks are never too hot. | |
* | |
*/ | |
private int[] drinkBytecodeChange() { | |
final int[] successes = {0,0}; | |
try { | |
CtClass methodItemsCt = HookManager.getInstance().getClassPool().get("com.wurmonline.server.behaviours.MethodsItems"); | |
CtMethod drinkCt = methodItemsCt.getDeclaredMethod("drink"); | |
drinkCt.instrument(new ExprEditor() { | |
@Override | |
public void edit(MethodCall methodCall) throws CannotCompileException { | |
if (Objects.equals(methodCall.getMethodName(), "getFoodComplexity")) { | |
methodCall.replace("$_ = 2.0;"); | |
successes[0] = 1; | |
} | |
else if (Objects.equals(methodCall.getMethodName(), "getTemperature")) { | |
methodCall.replace("$_ = 299;"); | |
successes[1] = 1; | |
} | |
} | |
}); | |
}catch (NotFoundException | CannotCompileException e) { | |
logger.warning(e.getMessage()); | |
} | |
return successes; | |
} | |
private static void evaluateChangesArray(int[] ints) { | |
boolean changesSuccessful = Arrays.stream(ints).noneMatch(value -> value == 0); | |
if (changesSuccessful) { | |
logger.log(Level.INFO, "simple food bonuses changes SUCCESS"); | |
} else { | |
logger.log(Level.INFO, "simple food bonuses changes FAILURE"); | |
logger.log(Level.FINE, Arrays.toString(ints)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment