Added Puppets on Aggro + Guild/Alliance packet info patch + Pet flags
Added pet flags recognition, such as the "pet speed same as owner" mechanic. Fixed repeatable quest "Remnants of HT..." not rewarding Dragon Stones. Refactored character object's check slots method, now using the same algorithm from the API class. Fixed a vunerability from before reviving/respawning players to towns, on where players would get their HP restored in area map before sending them back to safety. Fixed some NPC gates in Mushking Empire, allowing players to access bosses free of quest requirements. Improved dialog of NPCs for "permission to attempt Zakum expeds". Implemented (or rather improved) item scripts, now using NPC conversation methods as it was intended originally. Rehauled mob-skill "summon mobs" limit, now using the placeholders found in the wz to determine limit of concurrent underlings spawned, and "limit" now refers to total of underlings spawned from a mob. Revised IoSession closing mechanics in several login classes. Implemented automated loggedin account shutdown if another player has gained a pass from the DB to login. Improved the server-side check for teleport rocks. Fixed removeAfter from mobs being procced after they were disposed. Reviewed EIM start references on several scripts, minding the latest EIM setup implementations. Fixed equipments that were reused Scissors of Karma not not being able to sell on pshops/merchants. Fixed a bug where entering alliances would lead a player to see information from other guilds of past alliances until an update takes place. Padronized a few skillbook names. Reviewed player puppets not gaining priority properly on the recent aggro system. Improved "item sold" message of merchants, now displaying also quantity left of an item on store. Fixed a bug with itemid limits of weapons on server.
This commit is contained in:
@@ -228,7 +228,11 @@ public class AbstractPlayerInteraction {
|
||||
}
|
||||
|
||||
public boolean canHold(int itemid, int quantity) {
|
||||
return getPlayer().canHold(itemid, quantity);
|
||||
return canHoldAll(Collections.singletonList(itemid), Collections.singletonList(quantity), true);
|
||||
}
|
||||
|
||||
public boolean canHold(int itemid, int quantity, int removeItemid, int removeQuantity) {
|
||||
return canHoldAllAfterRemoving(Collections.singletonList(itemid), Collections.singletonList(quantity), Collections.singletonList(removeItemid), Collections.singletonList(removeQuantity));
|
||||
}
|
||||
|
||||
private static List<Integer> convertToIntegerArray(List<Double> list) {
|
||||
@@ -263,10 +267,6 @@ public class AbstractPlayerInteraction {
|
||||
return MapleInventory.checkSpots(c.getPlayer(), addedItems, false);
|
||||
}
|
||||
|
||||
public boolean canHold(int itemid, int quantity, int removeItemid, int removeQuantity) {
|
||||
return canHoldAllAfterRemoving(Collections.singletonList(itemid), Collections.singletonList(quantity), Collections.singletonList(removeItemid), Collections.singletonList(removeQuantity));
|
||||
}
|
||||
|
||||
private static List<Pair<Item, MapleInventoryType>> prepareProofInventoryItems(List<Pair<Integer, Integer>> items) {
|
||||
List<Pair<Item, MapleInventoryType>> addedItems = new LinkedList<>();
|
||||
for(Pair<Integer, Integer> p : items) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
@@ -19,17 +17,19 @@
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package scripting.item;
|
||||
package scripting.event;
|
||||
|
||||
import client.MapleClient;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kevintjuh93
|
||||
* @author Ronan
|
||||
*/
|
||||
public class ItemScriptMethods extends AbstractPlayerInteraction {
|
||||
public ItemScriptMethods(MapleClient c) {
|
||||
super(c);
|
||||
public class EventInstanceInProgressException extends Exception {
|
||||
|
||||
public static String EIIP_KEY = "Event instance ";
|
||||
|
||||
public EventInstanceInProgressException(String eventName, String eventInstance) {
|
||||
super(EIIP_KEY + "already in progress - " + eventName + ", EM: " + eventInstance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -260,7 +260,7 @@ public class EventManager {
|
||||
}
|
||||
}
|
||||
|
||||
public EventInstanceManager newInstance(String name) {
|
||||
public EventInstanceManager newInstance(String name) throws EventInstanceInProgressException {
|
||||
EventInstanceManager ret = getReadyInstance();
|
||||
|
||||
if(ret == null) {
|
||||
@@ -271,7 +271,7 @@ public class EventManager {
|
||||
|
||||
synchronized (instances) {
|
||||
if (instances.containsKey(name)) {
|
||||
return null;
|
||||
throw new EventInstanceInProgressException(name, this.getName());
|
||||
}
|
||||
|
||||
instances.put(name, ret);
|
||||
@@ -365,6 +365,34 @@ public class EventManager {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private String getInternalScriptExceptionMessage(Throwable a) {
|
||||
if (!(a instanceof ScriptException)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while(true) {
|
||||
Throwable t = a;
|
||||
a = a.getCause();
|
||||
|
||||
if (a == null) {
|
||||
return t.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EventInstanceManager createInstance(String name, Object... args) throws ScriptException, NoSuchMethodException {
|
||||
return (EventInstanceManager) iv.invokeFunction(name, args);
|
||||
}
|
||||
|
||||
private void registerEventInstance(String eventName, int lobbyId) {
|
||||
Integer oldLobby = instanceLocks.get(eventName);
|
||||
if (oldLobby != null) {
|
||||
setLockLobby(oldLobby, false);
|
||||
}
|
||||
|
||||
instanceLocks.put(eventName, lobbyId);
|
||||
}
|
||||
|
||||
public boolean startInstance(MapleExpedition exped) {
|
||||
return startInstance(-1, exped);
|
||||
}
|
||||
@@ -394,9 +422,14 @@ public class EventManager {
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
eim = (EventInstanceManager) (iv.invokeFunction("setup", leader.getClient().getChannel()));
|
||||
instanceLocks.put(eim.getName(), lobbyId);
|
||||
} catch (NullPointerException npe) {
|
||||
eim = createInstance("setup", leader.getClient().getChannel());
|
||||
registerEventInstance(eim.getName(), lobbyId);
|
||||
} catch (ScriptException | NullPointerException e) {
|
||||
String message = getInternalScriptExceptionMessage(e);
|
||||
if (message != null && !message.startsWith(EventInstanceInProgressException.EIIP_KEY)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
if(lobbyId > -1) {
|
||||
setLockLobby(lobbyId, false);
|
||||
}
|
||||
@@ -460,9 +493,14 @@ public class EventManager {
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : leader.getId()));
|
||||
instanceLocks.put(eim.getName(), lobbyId);
|
||||
} catch (NullPointerException npe) {
|
||||
eim = createInstance("setup", difficulty, (lobbyId > -1) ? lobbyId : leader.getId());
|
||||
registerEventInstance(eim.getName(), lobbyId);
|
||||
} catch (ScriptException | NullPointerException e) {
|
||||
String message = getInternalScriptExceptionMessage(e);
|
||||
if (message != null && !message.startsWith(EventInstanceInProgressException.EIIP_KEY)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
if(lobbyId > -1) {
|
||||
setLockLobby(lobbyId, false);
|
||||
}
|
||||
@@ -520,9 +558,14 @@ public class EventManager {
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
|
||||
instanceLocks.put(eim.getName(), lobbyId);
|
||||
} catch (NullPointerException npe) {
|
||||
eim = createInstance("setup", (Object) null);
|
||||
registerEventInstance(eim.getName(), lobbyId);
|
||||
} catch (ScriptException | NullPointerException e) {
|
||||
String message = getInternalScriptExceptionMessage(e);
|
||||
if (message != null && !message.startsWith(EventInstanceInProgressException.EIIP_KEY)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
if(lobbyId > -1) {
|
||||
setLockLobby(lobbyId, false);
|
||||
}
|
||||
@@ -582,9 +625,14 @@ public class EventManager {
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : party.getLeaderId()));
|
||||
instanceLocks.put(eim.getName(), lobbyId);
|
||||
} catch (NullPointerException npe) {
|
||||
eim = createInstance("setup", difficulty, (lobbyId > -1) ? lobbyId : party.getLeaderId());
|
||||
registerEventInstance(eim.getName(), lobbyId);
|
||||
} catch (ScriptException | NullPointerException e) {
|
||||
String message = getInternalScriptExceptionMessage(e);
|
||||
if (message != null && !message.startsWith(EventInstanceInProgressException.EIIP_KEY)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
if(lobbyId > -1) {
|
||||
setLockLobby(lobbyId, false);
|
||||
}
|
||||
@@ -652,7 +700,7 @@ public class EventManager {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
instanceLocks.put(eim.getName(), lobbyId);
|
||||
registerEventInstance(eim.getName(), lobbyId);
|
||||
eim.setLeader(leader);
|
||||
|
||||
iv.invokeFunction("setup", eim);
|
||||
|
||||
@@ -22,21 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package scripting.item;
|
||||
|
||||
import client.MapleClient;
|
||||
import constants.ServerConstants;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.script.Compilable;
|
||||
import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import scripting.npc.NPCScriptManager;
|
||||
import server.MapleItemInformationProvider.ScriptedItem;
|
||||
|
||||
public class ItemScriptManager {
|
||||
|
||||
@@ -46,60 +33,7 @@ public class ItemScriptManager {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Map<String, Invocable> scripts = new HashMap<>();
|
||||
private ScriptEngineFactory sef;
|
||||
|
||||
private ItemScriptManager() {
|
||||
ScriptEngineManager sem = new ScriptEngineManager();
|
||||
sef = sem.getEngineByName("javascript").getFactory();
|
||||
}
|
||||
|
||||
public boolean scriptExists(String scriptName) {
|
||||
File scriptFile = new File("scripts/item/" + scriptName + ".js");
|
||||
return scriptFile.exists();
|
||||
}
|
||||
|
||||
public void runItemScript(MapleClient c, String scriptName) {
|
||||
if (scripts.containsKey(scriptName)) {
|
||||
try {
|
||||
scripts.get(scriptName).invokeFunction("start", new ItemScriptMethods(c));
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
FilePrinter.printError(FilePrinter.ITEM + scriptName + ".txt", ex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
File scriptFile = new File("scripts/item/" + scriptName + ".js");
|
||||
if (!scriptFile.exists()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
FileReader fr = null;
|
||||
ScriptEngine portal = sef.getScriptEngine();
|
||||
try {
|
||||
fr = new FileReader(scriptFile);
|
||||
|
||||
// java 8 support here thanks to Arufonsu
|
||||
if (ServerConstants.JAVA_8){
|
||||
portal.eval("load('nashorn:mozilla_compat.js');" + System.lineSeparator());
|
||||
}
|
||||
|
||||
((Compilable) portal).compile(fr).eval();
|
||||
|
||||
final Invocable script = ((Invocable) portal);
|
||||
scripts.put(scriptName, script);
|
||||
script.invokeFunction("start", new ItemScriptMethods(c));
|
||||
} catch (final UndeclaredThrowableException | ScriptException ute) {
|
||||
FilePrinter.printError(FilePrinter.ITEM + scriptName + ".txt", ute);
|
||||
} catch (final Exception e) {
|
||||
FilePrinter.printError(FilePrinter.ITEM + scriptName + ".txt", e);
|
||||
} finally {
|
||||
if (fr != null) {
|
||||
try {
|
||||
fr.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void runItemScript(MapleClient c, ScriptedItem scriptItem) {
|
||||
NPCScriptManager.getInstance().start(c, scriptItem, null);
|
||||
}
|
||||
}
|
||||
@@ -78,18 +78,18 @@ public class MapScriptManager {
|
||||
return;
|
||||
}
|
||||
FileReader fr = null;
|
||||
ScriptEngine portal = sef.getScriptEngine();
|
||||
ScriptEngine se = sef.getScriptEngine();
|
||||
try {
|
||||
fr = new FileReader(scriptFile);
|
||||
|
||||
// java 8 support here thanks to Arufonsu
|
||||
if (ServerConstants.JAVA_8){
|
||||
portal.eval("load('nashorn:mozilla_compat.js');" + System.lineSeparator());
|
||||
se.eval("load('nashorn:mozilla_compat.js');" + System.lineSeparator());
|
||||
}
|
||||
|
||||
((Compilable) portal).compile(fr).eval();
|
||||
((Compilable) se).compile(fr).eval();
|
||||
|
||||
final Invocable script = ((Invocable) portal);
|
||||
final Invocable script = ((Invocable) se);
|
||||
scripts.put(scriptName, script);
|
||||
script.invokeFunction("start", new MapScriptMethods(c));
|
||||
} catch (final UndeclaredThrowableException | ScriptException ute) {
|
||||
|
||||
@@ -74,16 +74,18 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
||||
private int npcOid;
|
||||
private String scriptName;
|
||||
private String getText;
|
||||
private boolean itemScript;
|
||||
|
||||
public NPCConversationManager(MapleClient c, int npc, String scriptName) {
|
||||
this(c, npc, -1, scriptName);
|
||||
this(c, npc, -1, scriptName, false);
|
||||
}
|
||||
|
||||
public NPCConversationManager(MapleClient c, int npc, int oid, String scriptName) {
|
||||
public NPCConversationManager(MapleClient c, int npc, int oid, String scriptName, boolean itemScript) {
|
||||
super(c);
|
||||
this.npc = npc;
|
||||
this.npcOid = oid;
|
||||
this.scriptName = scriptName;
|
||||
this.itemScript = itemScript;
|
||||
}
|
||||
|
||||
public int getNpc() {
|
||||
@@ -97,6 +99,14 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
public boolean isItemScript() {
|
||||
return itemScript;
|
||||
}
|
||||
|
||||
public void resetItemScript() {
|
||||
this.itemScript = false;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
NPCScriptManager.getInstance().dispose(this);
|
||||
|
||||
@@ -32,6 +32,7 @@ import javax.script.Invocable;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import scripting.AbstractScriptManager;
|
||||
import server.MapleItemInformationProvider.ScriptedItem;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
@@ -60,7 +61,7 @@ public class NPCScriptManager extends AbstractScriptManager {
|
||||
}
|
||||
|
||||
public boolean start(MapleClient c, int npc, MapleCharacter chr) {
|
||||
return start(c, npc, null, chr);
|
||||
return start(c, npc, -1, chr);
|
||||
}
|
||||
|
||||
public boolean start(MapleClient c, int npc, int oid, MapleCharacter chr) {
|
||||
@@ -70,27 +71,42 @@ public class NPCScriptManager extends AbstractScriptManager {
|
||||
public boolean start(MapleClient c, int npc, String fileName, MapleCharacter chr) {
|
||||
return start(c, npc, -1, fileName, chr);
|
||||
}
|
||||
|
||||
|
||||
public boolean start(MapleClient c, int npc, int oid, String fileName, MapleCharacter chr) {
|
||||
return start(c, npc, oid, fileName, chr, false, "cm");
|
||||
}
|
||||
|
||||
public boolean start(MapleClient c, ScriptedItem scriptItem, MapleCharacter chr) {
|
||||
return start(c, scriptItem.getNpc(), -1, scriptItem.getScript(), chr, true, "im");
|
||||
}
|
||||
|
||||
private boolean start(MapleClient c, int npc, int oid, String fileName, MapleCharacter chr, boolean itemScript, String engineName) {
|
||||
try {
|
||||
NPCConversationManager cm = new NPCConversationManager(c, npc, oid, fileName);
|
||||
NPCConversationManager cm = new NPCConversationManager(c, npc, oid, fileName, itemScript);
|
||||
if (cms.containsKey(c)) {
|
||||
dispose(c);
|
||||
}
|
||||
if (c.canClickNPC()) {
|
||||
cms.put(c, cm);
|
||||
Invocable iv = null;
|
||||
if (fileName != null) {
|
||||
iv = getInvocable("npc/" + fileName + ".js", c);
|
||||
if (!itemScript) {
|
||||
if (fileName != null) {
|
||||
iv = getInvocable("npc/" + fileName + ".js", c);
|
||||
}
|
||||
} else {
|
||||
if (fileName != null) { // thanks MiLin for drafting NPC-based item scripts
|
||||
iv = getInvocable("item/" + fileName + ".js", c);
|
||||
}
|
||||
}
|
||||
if (iv == null) {
|
||||
iv = getInvocable("npc/" + npc + ".js", c);
|
||||
cm.resetItemScript();
|
||||
}
|
||||
if (iv == null || NPCScriptManager.getInstance() == null) {
|
||||
dispose(c);
|
||||
return false;
|
||||
}
|
||||
engine.put("cm", cm);
|
||||
engine.put(engineName, cm);
|
||||
scripts.put(c, iv);
|
||||
c.setClickedNPC();
|
||||
try {
|
||||
@@ -142,10 +158,11 @@ public class NPCScriptManager extends AbstractScriptManager {
|
||||
cms.remove(c);
|
||||
scripts.remove(c);
|
||||
|
||||
String scriptFolder = (cm.isItemScript() ? "item" : "npc");
|
||||
if(cm.getScriptName() != null) {
|
||||
resetContext("npc/" + cm.getScriptName() + ".js", c);
|
||||
resetContext(scriptFolder + "/" + cm.getScriptName() + ".js", c);
|
||||
} else {
|
||||
resetContext("npc/" + cm.getNpc() + ".js", c);
|
||||
resetContext(scriptFolder + "/" + cm.getNpc() + ".js", c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user