Switch to Maven file structure
This commit is contained in:
1228
src/main/java/scripting/AbstractPlayerInteraction.java
Normal file
1228
src/main/java/scripting/AbstractPlayerInteraction.java
Normal file
File diff suppressed because it is too large
Load Diff
80
src/main/java/scripting/AbstractScriptManager.java
Normal file
80
src/main/java/scripting/AbstractScriptManager.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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;
|
||||
|
||||
import client.MapleClient;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.script.*;
|
||||
|
||||
import constants.net.ServerConstants;
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import tools.FilePrinter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public abstract class AbstractScriptManager {
|
||||
private ScriptEngineFactory sef;
|
||||
|
||||
protected AbstractScriptManager() {
|
||||
sef = new ScriptEngineManager().getEngineByName("javascript").getFactory();
|
||||
}
|
||||
|
||||
protected NashornScriptEngine getScriptEngine(String path) {
|
||||
path = "scripts/" + path;
|
||||
File scriptFile = new File(path);
|
||||
if (!scriptFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
NashornScriptEngine engine = (NashornScriptEngine) sef.getScriptEngine();
|
||||
try (FileReader fr = new FileReader(scriptFile)) {
|
||||
if (ServerConstants.JAVA_8){
|
||||
engine.eval("load('nashorn:mozilla_compat.js');" + System.lineSeparator());
|
||||
}
|
||||
engine.eval(fr);
|
||||
} catch (final ScriptException | IOException t) {
|
||||
FilePrinter.printError(FilePrinter.INVOCABLE + path.substring(12), t, path);
|
||||
return null;
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
protected NashornScriptEngine getScriptEngine(String path, MapleClient c) {
|
||||
NashornScriptEngine engine = c.getScriptEngine("scripts/" + path);
|
||||
if (engine == null) {
|
||||
engine = getScriptEngine(path);
|
||||
c.setScriptEngine(path, engine);
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
protected void resetContext(String path, MapleClient c) {
|
||||
c.removeScriptEngine("scripts/" + path);
|
||||
}
|
||||
}
|
||||
1407
src/main/java/scripting/event/EventInstanceManager.java
Normal file
1407
src/main/java/scripting/event/EventInstanceManager.java
Normal file
File diff suppressed because it is too large
Load Diff
984
src/main/java/scripting/event/EventManager.java
Normal file
984
src/main/java/scripting/event/EventManager.java
Normal file
@@ -0,0 +1,984 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.event;
|
||||
|
||||
import config.YamlConfig;
|
||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
import jdk.nashorn.api.scripting.ScriptUtils;
|
||||
import tools.exceptions.EventInstanceInProgressException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import constants.net.ServerConstants;
|
||||
import constants.game.GameConstants;
|
||||
import client.MapleCharacter;
|
||||
import net.server.Server;
|
||||
import net.server.world.World;
|
||||
import net.server.channel.Channel;
|
||||
import net.server.guild.MapleGuild;
|
||||
import net.server.world.MapleParty;
|
||||
import net.server.world.MaplePartyCharacter;
|
||||
import scripting.event.scheduler.EventScriptScheduler;
|
||||
import server.MapleMarriage;
|
||||
import server.expeditions.MapleExpedition;
|
||||
import server.maps.MapleMap;
|
||||
import server.life.MapleMonster;
|
||||
import server.life.MapleLifeFactory;
|
||||
import server.quest.MapleQuest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import net.server.audit.LockCollector;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import server.ThreadManager;
|
||||
//import jdk.nashorn.api.scripting.ScriptUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
* @author Ronan
|
||||
*/
|
||||
public class EventManager {
|
||||
private NashornScriptEngine iv;
|
||||
private Channel cserv;
|
||||
private World wserv;
|
||||
private Server server;
|
||||
private EventScriptScheduler ess = new EventScriptScheduler();
|
||||
private Map<String, EventInstanceManager> instances = new HashMap<String, EventInstanceManager>();
|
||||
private Map<String, Integer> instanceLocks = new HashMap<String, Integer>();
|
||||
private final Queue<Integer> queuedGuilds = new LinkedList<>();
|
||||
private final Map<Integer, Integer> queuedGuildLeaders = new HashMap<>();
|
||||
private List<Boolean> openedLobbys;
|
||||
private List<EventInstanceManager> readyInstances = new LinkedList<>();
|
||||
private Integer readyId = 0, onLoadInstances = 0;
|
||||
private Properties props = new Properties();
|
||||
private String name;
|
||||
private MonitoredReentrantLock lobbyLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_LOBBY);
|
||||
private MonitoredReentrantLock queueLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_QUEUE);
|
||||
private MonitoredReentrantLock startLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_START);
|
||||
|
||||
private Set<Integer> playerPermit = new HashSet<>();
|
||||
private Semaphore startSemaphore = new Semaphore(7);
|
||||
|
||||
private static final int maxLobbys = 8; // an event manager holds up to this amount of concurrent lobbys
|
||||
|
||||
public EventManager(Channel cserv, NashornScriptEngine iv, String name) {
|
||||
this.server = Server.getInstance();
|
||||
this.iv = iv;
|
||||
this.cserv = cserv;
|
||||
this.wserv = server.getWorld(cserv.getWorld());
|
||||
this.name = name;
|
||||
|
||||
this.openedLobbys = new ArrayList<>();
|
||||
for(int i = 0; i < maxLobbys; i++) this.openedLobbys.add(false);
|
||||
}
|
||||
|
||||
private boolean isDisposed() {
|
||||
return onLoadInstances <= -1000;
|
||||
}
|
||||
|
||||
public void cancel() { // make sure to only call this when there are NO PLAYERS ONLINE to mess around with the event manager!
|
||||
ess.dispose();
|
||||
|
||||
try {
|
||||
iv.invokeFunction("cancelSchedule", (Object) null);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
Collection<EventInstanceManager> eimList;
|
||||
synchronized(instances) {
|
||||
eimList = getInstances();
|
||||
instances.clear();
|
||||
}
|
||||
|
||||
for(EventInstanceManager eim : eimList) {
|
||||
eim.dispose(true);
|
||||
}
|
||||
|
||||
List<EventInstanceManager> readyEims;
|
||||
queueLock.lock();
|
||||
try {
|
||||
readyEims = new ArrayList<>(readyInstances);
|
||||
readyInstances.clear();
|
||||
onLoadInstances = Integer.MIN_VALUE / 2;
|
||||
} finally {
|
||||
queueLock.unlock();
|
||||
}
|
||||
|
||||
for(EventInstanceManager eim : readyEims) {
|
||||
eim.dispose(true);
|
||||
}
|
||||
|
||||
props.clear();
|
||||
cserv = null;
|
||||
wserv = null;
|
||||
server = null;
|
||||
iv = null;
|
||||
|
||||
disposeLocks();
|
||||
}
|
||||
|
||||
private void disposeLocks() {
|
||||
LockCollector.getInstance().registerDisposeAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
emptyLocks();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void emptyLocks() {
|
||||
lobbyLock = lobbyLock.dispose();
|
||||
queueLock = queueLock.dispose();
|
||||
startLock = startLock.dispose();
|
||||
}
|
||||
|
||||
private List<Integer> convertToIntegerArray(List<Object> list) {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
|
||||
if (ServerConstants.JAVA_8) {
|
||||
for (Object d: list) {
|
||||
intList.add(((Integer) d).intValue());
|
||||
}
|
||||
} else {
|
||||
for (Object d: list) {
|
||||
intList.add(((Double) d).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
return intList;
|
||||
}
|
||||
|
||||
public long getLobbyDelay() {
|
||||
return YamlConfig.config.server.EVENT_LOBBY_DELAY;
|
||||
}
|
||||
|
||||
private List<Integer> getLobbyRange() {
|
||||
try {
|
||||
if (!ServerConstants.JAVA_8) {
|
||||
return convertToIntegerArray((List<Object>)iv.invokeFunction("setLobbyRange", (Object) null));
|
||||
} else { // java 8 support here thanks to MedicOP
|
||||
ScriptObjectMirror object = (ScriptObjectMirror) iv.invokeFunction("setLobbyRange", (Object) null);
|
||||
int[] to = object.to(int[].class);
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (int i : to) {
|
||||
list.add(i);
|
||||
}
|
||||
return list;
|
||||
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) { // they didn't define a lobby range
|
||||
List<Integer> defaultRange = new ArrayList<>();
|
||||
defaultRange.add(0);
|
||||
defaultRange.add(maxLobbys);
|
||||
|
||||
return defaultRange;
|
||||
}
|
||||
}
|
||||
|
||||
public EventScheduledFuture schedule(String methodName, long delay) {
|
||||
return schedule(methodName, null, delay);
|
||||
}
|
||||
|
||||
public EventScheduledFuture schedule(final String methodName, final EventInstanceManager eim, long delay) {
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
iv.invokeFunction(methodName, eim);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ess.registerEntry(r, delay);
|
||||
|
||||
// hate to do that, but those schedules can still be cancelled, so well... Let GC do it's job
|
||||
return new EventScheduledFuture(r, ess);
|
||||
}
|
||||
|
||||
public EventScheduledFuture scheduleAtTimestamp(final String methodName, long timestamp) {
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
iv.invokeFunction(methodName, (Object) null);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ess.registerEntry(r, timestamp - server.getCurrentTime());
|
||||
return new EventScheduledFuture(r, ess);
|
||||
}
|
||||
|
||||
public World getWorldServer() {
|
||||
return wserv;
|
||||
}
|
||||
|
||||
public Channel getChannelServer() {
|
||||
return cserv;
|
||||
}
|
||||
|
||||
public NashornScriptEngine getIv() {
|
||||
return iv;
|
||||
}
|
||||
|
||||
public EventInstanceManager getInstance(String name) {
|
||||
return instances.get(name);
|
||||
}
|
||||
|
||||
public Collection<EventInstanceManager> getInstances() {
|
||||
synchronized (instances) {
|
||||
return new LinkedList<>(instances.values());
|
||||
}
|
||||
}
|
||||
|
||||
public EventInstanceManager newInstance(String name) throws EventInstanceInProgressException {
|
||||
EventInstanceManager ret = getReadyInstance();
|
||||
|
||||
if(ret == null) {
|
||||
ret = new EventInstanceManager(this, name);
|
||||
} else {
|
||||
ret.setName(name);
|
||||
}
|
||||
|
||||
synchronized (instances) {
|
||||
if (instances.containsKey(name)) {
|
||||
throw new EventInstanceInProgressException(name, this.getName());
|
||||
}
|
||||
|
||||
instances.put(name, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public MapleMarriage newMarriage(String name) throws EventInstanceInProgressException {
|
||||
MapleMarriage ret = new MapleMarriage(this, name);
|
||||
|
||||
synchronized (instances) {
|
||||
if (instances.containsKey(name)) {
|
||||
throw new EventInstanceInProgressException(name, this.getName());
|
||||
}
|
||||
|
||||
instances.put(name, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void disposeInstance(final String name) {
|
||||
ess.registerEntry(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
freeLobbyInstance(name);
|
||||
|
||||
synchronized (instances) {
|
||||
instances.remove(name);
|
||||
}
|
||||
}
|
||||
}, YamlConfig.config.server.EVENT_LOBBY_DELAY * 1000);
|
||||
}
|
||||
|
||||
public void setProperty(String key, String value) {
|
||||
props.setProperty(key, value);
|
||||
}
|
||||
|
||||
public void setIntProperty(String key, int value) {
|
||||
setProperty(key, value);
|
||||
}
|
||||
|
||||
public void setProperty(String key, int value) {
|
||||
props.setProperty(key, value + "");
|
||||
}
|
||||
|
||||
public String getProperty(String key) {
|
||||
return props.getProperty(key);
|
||||
}
|
||||
|
||||
public int getIntProperty(String key) {
|
||||
return Integer.parseInt(props.getProperty(key));
|
||||
}
|
||||
|
||||
private void setLockLobby(int lobbyId, boolean lock) {
|
||||
lobbyLock.lock();
|
||||
try {
|
||||
openedLobbys.set(lobbyId, lock);
|
||||
} finally {
|
||||
lobbyLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean startLobbyInstance(int lobbyId) {
|
||||
lobbyLock.lock();
|
||||
try {
|
||||
if (lobbyId < 0) {
|
||||
lobbyId = 0;
|
||||
} else if (lobbyId >= maxLobbys) {
|
||||
lobbyId = maxLobbys - 1;
|
||||
}
|
||||
|
||||
if(!openedLobbys.get(lobbyId)) {
|
||||
openedLobbys.set(lobbyId, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
lobbyLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void freeLobbyInstance(String lobbyName) {
|
||||
Integer i = instanceLocks.get(lobbyName);
|
||||
if(i == null) return;
|
||||
|
||||
instanceLocks.remove(lobbyName);
|
||||
if(i > -1) setLockLobby(i, false);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private int availableLobbyInstance() {
|
||||
List<Integer> lr = getLobbyRange();
|
||||
int lb = 0, hb = 0;
|
||||
|
||||
if(lr.size() >= 2) {
|
||||
lb = Math.max(lr.get(0), 0);
|
||||
hb = Math.min(lr.get(1), maxLobbys - 1);
|
||||
}
|
||||
|
||||
for(int i = lb; i <= hb; i++) {
|
||||
if(startLobbyInstance(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, MapleExpedition exped) {
|
||||
return startInstance(lobbyId, exped, exped.getLeader());
|
||||
}
|
||||
|
||||
//Expedition method: starts an expedition
|
||||
public boolean startInstance(int lobbyId, MapleExpedition exped, MapleCharacter leader) {
|
||||
if (this.isDisposed()) return false;
|
||||
|
||||
try {
|
||||
if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
|
||||
playerPermit.add(leader.getId());
|
||||
|
||||
startLock.lock();
|
||||
try {
|
||||
try {
|
||||
if(lobbyId == -1) {
|
||||
lobbyId = availableLobbyInstance();
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
eim.setLeader(leader);
|
||||
|
||||
exped.start();
|
||||
eim.registerExpedition(exped);
|
||||
|
||||
eim.startEvent();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
startLock.unlock();
|
||||
playerPermit.remove(leader.getId());
|
||||
startSemaphore.release();
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException ie) {
|
||||
playerPermit.remove(leader.getId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Regular method: player
|
||||
public boolean startInstance(MapleCharacter chr) {
|
||||
return startInstance(-1, chr);
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, MapleCharacter leader) {
|
||||
return startInstance(lobbyId, leader, leader, 1);
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, MapleCharacter chr, MapleCharacter leader, int difficulty) {
|
||||
if (this.isDisposed()) return false;
|
||||
|
||||
try {
|
||||
if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
|
||||
playerPermit.add(leader.getId());
|
||||
|
||||
startLock.lock();
|
||||
try {
|
||||
try {
|
||||
if(lobbyId == -1) {
|
||||
lobbyId = availableLobbyInstance();
|
||||
if(lobbyId == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!startLobbyInstance(lobbyId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
eim.setLeader(leader);
|
||||
|
||||
if(chr != null) eim.registerPlayer(chr);
|
||||
|
||||
eim.startEvent();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
startLock.unlock();
|
||||
playerPermit.remove(leader.getId());
|
||||
startSemaphore.release();
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException ie) {
|
||||
playerPermit.remove(leader.getId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//PQ method: starts a PQ
|
||||
public boolean startInstance(MapleParty party, MapleMap map) {
|
||||
return startInstance(-1, party, map);
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map) {
|
||||
return startInstance(lobbyId, party, map, party.getLeader().getPlayer());
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, MapleCharacter leader) {
|
||||
if (this.isDisposed()) return false;
|
||||
|
||||
try {
|
||||
if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
|
||||
playerPermit.add(leader.getId());
|
||||
|
||||
startLock.lock();
|
||||
try {
|
||||
try {
|
||||
if(lobbyId == -1) {
|
||||
lobbyId = availableLobbyInstance();
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
eim.setLeader(leader);
|
||||
|
||||
eim.registerParty(party, map);
|
||||
party.setEligibleMembers(null);
|
||||
|
||||
eim.startEvent();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
startLock.unlock();
|
||||
playerPermit.remove(leader.getId());
|
||||
startSemaphore.release();
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException ie) {
|
||||
playerPermit.remove(leader.getId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//PQ method: starts a PQ with a difficulty level, requires function setup(difficulty, leaderid) instead of setup()
|
||||
public boolean startInstance(MapleParty party, MapleMap map, int difficulty) {
|
||||
return startInstance(-1, party, map, difficulty);
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, int difficulty) {
|
||||
return startInstance(lobbyId, party, map, difficulty, party.getLeader().getPlayer());
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, int difficulty, MapleCharacter leader) {
|
||||
if (this.isDisposed()) return false;
|
||||
|
||||
try {
|
||||
if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
|
||||
playerPermit.add(leader.getId());
|
||||
|
||||
startLock.lock();
|
||||
try {
|
||||
try {
|
||||
if(lobbyId == -1) {
|
||||
lobbyId = availableLobbyInstance();
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
EventInstanceManager eim;
|
||||
try {
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
eim.setLeader(leader);
|
||||
|
||||
eim.registerParty(party, map);
|
||||
party.setEligibleMembers(null);
|
||||
|
||||
eim.startEvent();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
startLock.unlock();
|
||||
playerPermit.remove(leader.getId());
|
||||
startSemaphore.release();
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException ie) {
|
||||
playerPermit.remove(leader.getId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//non-PQ method for starting instance
|
||||
public boolean startInstance(EventInstanceManager eim, String ldr) {
|
||||
return startInstance(-1, eim, ldr);
|
||||
}
|
||||
|
||||
public boolean startInstance(EventInstanceManager eim, MapleCharacter ldr) {
|
||||
return startInstance(-1, eim, ldr.getName(), ldr);
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, EventInstanceManager eim, String ldr) {
|
||||
return startInstance(-1, eim, ldr, eim.getEm().getChannelServer().getPlayerStorage().getCharacterByName(ldr)); // things they make me do...
|
||||
}
|
||||
|
||||
public boolean startInstance(int lobbyId, EventInstanceManager eim, String ldr, MapleCharacter leader) {
|
||||
if (this.isDisposed()) return false;
|
||||
|
||||
try {
|
||||
if(!playerPermit.contains(leader.getId()) && startSemaphore.tryAcquire(7777, TimeUnit.MILLISECONDS)) {
|
||||
playerPermit.add(leader.getId());
|
||||
|
||||
startLock.lock();
|
||||
try {
|
||||
try {
|
||||
if(lobbyId == -1) {
|
||||
lobbyId = availableLobbyInstance();
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
if(eim == null) {
|
||||
if(lobbyId > -1) {
|
||||
setLockLobby(lobbyId, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
registerEventInstance(eim.getName(), lobbyId);
|
||||
eim.setLeader(leader);
|
||||
|
||||
iv.invokeFunction("setup", eim);
|
||||
eim.setProperty("leader", ldr);
|
||||
|
||||
eim.startEvent();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
startLock.unlock();
|
||||
playerPermit.remove(leader.getId());
|
||||
startSemaphore.release();
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException ie) {
|
||||
playerPermit.remove(leader.getId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<MaplePartyCharacter> getEligibleParty(MapleParty party) {
|
||||
if (party == null) {
|
||||
return(new ArrayList<>());
|
||||
}
|
||||
try {
|
||||
Object p = iv.invokeFunction("getEligibleParty", party.getPartyMembersOnline());
|
||||
|
||||
if(p != null) {
|
||||
List<MaplePartyCharacter> lmpc;
|
||||
|
||||
if(ServerConstants.JAVA_8) {
|
||||
lmpc = new ArrayList<>(((Map<String, MaplePartyCharacter>)(ScriptUtils.convert(p, Map.class))).values());
|
||||
} else {
|
||||
lmpc = new ArrayList<>((List<MaplePartyCharacter>) p);
|
||||
}
|
||||
|
||||
party.setEligibleMembers(lmpc);
|
||||
return lmpc;
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return(new ArrayList<>());
|
||||
}
|
||||
|
||||
public void clearPQ(EventInstanceManager eim) {
|
||||
try {
|
||||
iv.invokeFunction("clearPQ", eim);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearPQ(EventInstanceManager eim, MapleMap toMap) {
|
||||
try {
|
||||
iv.invokeFunction("clearPQ", eim, toMap);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public MapleMonster getMonster(int mid) {
|
||||
return(MapleLifeFactory.getMonster(mid));
|
||||
}
|
||||
|
||||
private void exportReadyGuild(Integer guildId) {
|
||||
MapleGuild mg = server.getGuild(guildId);
|
||||
String callout = "[Guild Quest] Your guild has been registered to attend to the Sharenian Guild Quest at channel " + this.getChannelServer().getId()
|
||||
+ " and HAS JUST STARTED THE STRATEGY PHASE. After 3 minutes, no more guild members will be allowed to join the effort."
|
||||
+ " Check out Shuang at the excavation site in Perion for more info.";
|
||||
|
||||
mg.dropMessage(6, callout);
|
||||
}
|
||||
|
||||
private void exportMovedQueueToGuild(Integer guildId, int place) {
|
||||
MapleGuild mg = server.getGuild(guildId);
|
||||
String callout = "[Guild Quest] Your guild has been registered to attend to the Sharenian Guild Quest at channel " + this.getChannelServer().getId()
|
||||
+ " and is currently on the " + GameConstants.ordinal(place) + " place on the waiting queue.";
|
||||
|
||||
mg.dropMessage(6, callout);
|
||||
}
|
||||
|
||||
private List<Integer> getNextGuildQueue() {
|
||||
synchronized(queuedGuilds) {
|
||||
Integer guildId = queuedGuilds.poll();
|
||||
if(guildId == null) return null;
|
||||
|
||||
wserv.removeGuildQueued(guildId);
|
||||
Integer leaderId = queuedGuildLeaders.remove(guildId);
|
||||
|
||||
int place = 1;
|
||||
for(Integer i: queuedGuilds) {
|
||||
exportMovedQueueToGuild(i, place);
|
||||
place++;
|
||||
}
|
||||
|
||||
List<Integer> list = new ArrayList<>(2);
|
||||
list.add(guildId); list.add(leaderId);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isQueueFull() {
|
||||
synchronized(queuedGuilds) {
|
||||
return queuedGuilds.size() >= YamlConfig.config.server.EVENT_MAX_GUILD_QUEUE;
|
||||
}
|
||||
}
|
||||
|
||||
public int getQueueSize() {
|
||||
synchronized(queuedGuilds) {
|
||||
return queuedGuilds.size();
|
||||
}
|
||||
}
|
||||
|
||||
public byte addGuildToQueue(Integer guildId, Integer leaderId) {
|
||||
if(wserv.isGuildQueued(guildId)) return -1;
|
||||
|
||||
if(!isQueueFull()) {
|
||||
boolean canStartAhead;
|
||||
synchronized(queuedGuilds) {
|
||||
canStartAhead = queuedGuilds.isEmpty();
|
||||
|
||||
queuedGuilds.add(guildId);
|
||||
wserv.putGuildQueued(guildId);
|
||||
queuedGuildLeaders.put(guildId, leaderId);
|
||||
|
||||
int place = queuedGuilds.size();
|
||||
exportMovedQueueToGuild(guildId, place);
|
||||
}
|
||||
|
||||
if(canStartAhead) {
|
||||
if(!attemptStartGuildInstance()) {
|
||||
synchronized(queuedGuilds) {
|
||||
queuedGuilds.add(guildId);
|
||||
wserv.putGuildQueued(guildId);
|
||||
queuedGuildLeaders.put(guildId, leaderId);
|
||||
}
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean attemptStartGuildInstance() {
|
||||
MapleCharacter chr = null;
|
||||
List<Integer> guildInstance = null;
|
||||
while(chr == null) {
|
||||
guildInstance = getNextGuildQueue();
|
||||
if(guildInstance == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chr = cserv.getPlayerStorage().getCharacterById(guildInstance.get(1));
|
||||
}
|
||||
|
||||
if(startInstance(chr)) {
|
||||
exportReadyGuild(guildInstance.get(0));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void startQuest(MapleCharacter chr, int id, int npcid) {
|
||||
try {
|
||||
MapleQuest.getInstance(id).forceStart(chr, npcid);
|
||||
} catch (NullPointerException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void completeQuest(MapleCharacter chr, int id, int npcid) {
|
||||
try {
|
||||
MapleQuest.getInstance(id).forceComplete(chr, npcid);
|
||||
} catch (NullPointerException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTransportationTime(int travelTime) {
|
||||
return this.getWorldServer().getTransportationTime(travelTime);
|
||||
}
|
||||
|
||||
private void fillEimQueue() {
|
||||
ThreadManager.getInstance().newTask(new EventManagerTask()); //call new thread to fill up readied instances queue
|
||||
}
|
||||
|
||||
private EventInstanceManager getReadyInstance() {
|
||||
queueLock.lock();
|
||||
try {
|
||||
if(readyInstances.isEmpty()) {
|
||||
fillEimQueue();
|
||||
return null;
|
||||
}
|
||||
|
||||
EventInstanceManager eim = readyInstances.remove(0);
|
||||
fillEimQueue();
|
||||
|
||||
return eim;
|
||||
} finally {
|
||||
queueLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void instantiateQueuedInstance() {
|
||||
int nextEventId;
|
||||
queueLock.lock();
|
||||
try {
|
||||
if (this.isDisposed() || readyInstances.size() + onLoadInstances >= Math.ceil((double)maxLobbys / 3.0)) return;
|
||||
|
||||
onLoadInstances++;
|
||||
nextEventId = readyId;
|
||||
readyId++;
|
||||
} finally {
|
||||
queueLock.unlock();
|
||||
}
|
||||
|
||||
EventInstanceManager eim = new EventInstanceManager(this, "sampleName" + nextEventId);
|
||||
queueLock.lock();
|
||||
try {
|
||||
if (this.isDisposed()) { // EM already disposed
|
||||
return;
|
||||
}
|
||||
|
||||
readyInstances.add(eim);
|
||||
onLoadInstances--;
|
||||
} finally {
|
||||
queueLock.unlock();
|
||||
}
|
||||
|
||||
instantiateQueuedInstance(); // keep filling the queue until reach threshold.
|
||||
}
|
||||
|
||||
private class EventManagerTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
instantiateQueuedInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/main/java/scripting/event/EventScheduledFuture.java
Normal file
40
src/main/java/scripting/event/EventScheduledFuture.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 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
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.event;
|
||||
|
||||
import scripting.event.scheduler.EventScriptScheduler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public class EventScheduledFuture {
|
||||
Runnable r;
|
||||
EventScriptScheduler ess;
|
||||
|
||||
public EventScheduledFuture(Runnable r, EventScriptScheduler ess) {
|
||||
this.r = r;
|
||||
this.ess = ess;
|
||||
}
|
||||
|
||||
public void cancel(boolean dummy) { // will always implement "non-interrupt if running" regardless of boolean value
|
||||
ess.cancelEntry(r);
|
||||
}
|
||||
}
|
||||
136
src/main/java/scripting/event/EventScriptManager.java
Normal file
136
src/main/java/scripting/event/EventScriptManager.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.event;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
|
||||
import net.server.channel.Channel;
|
||||
import scripting.AbstractScriptManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public class EventScriptManager extends AbstractScriptManager {
|
||||
|
||||
private class EventEntry {
|
||||
|
||||
public EventEntry(NashornScriptEngine iv, EventManager em) {
|
||||
this.iv = iv;
|
||||
this.em = em;
|
||||
}
|
||||
public NashornScriptEngine iv;
|
||||
public EventManager em;
|
||||
}
|
||||
|
||||
private static EventEntry fallback;
|
||||
private Map<String, EventEntry> events = new ConcurrentHashMap<>();
|
||||
private boolean active = false;
|
||||
|
||||
public EventScriptManager(Channel cserv, String[] scripts) {
|
||||
super();
|
||||
for (String script : scripts) {
|
||||
if (!script.equals("")) {
|
||||
NashornScriptEngine iv = getScriptEngine("event/" + script + ".js");
|
||||
events.put(script, new EventEntry(iv, new EventManager(cserv, iv, script)));
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
fallback = events.remove("0_EXAMPLE");
|
||||
}
|
||||
|
||||
public EventManager getEventManager(String event) {
|
||||
EventEntry entry = events.get(event);
|
||||
if (entry == null) {
|
||||
return fallback.em;
|
||||
}
|
||||
return entry.em;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public final void init() {
|
||||
for (EventEntry entry : events.values()) {
|
||||
try {
|
||||
entry.iv.put("em", entry.em);
|
||||
entry.iv.invokeFunction("init", (Object) null);
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(EventScriptManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
System.out.println("Error on script: " + entry.em.getName());
|
||||
}
|
||||
}
|
||||
|
||||
active = events.size() > 1; // bootup loads only 1 script
|
||||
}
|
||||
|
||||
private void reloadScripts() {
|
||||
Set<Entry<String, EventEntry>> eventEntries = new HashSet<>(events.entrySet());
|
||||
if (eventEntries.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Channel cserv = eventEntries.iterator().next().getValue().em.getChannelServer();
|
||||
for (Entry<String, EventEntry> entry : eventEntries) {
|
||||
String script = entry.getKey();
|
||||
NashornScriptEngine iv = getScriptEngine("event/" + script + ".js");
|
||||
events.put(script, new EventEntry(iv, new EventManager(cserv, iv, script)));
|
||||
}
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
cancel();
|
||||
reloadScripts();
|
||||
init();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
active = false;
|
||||
for (EventEntry entry : events.values()) {
|
||||
entry.em.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (events.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<EventEntry> eventEntries = new HashSet<>(events.values());
|
||||
events.clear();
|
||||
|
||||
active = false;
|
||||
for (EventEntry entry : eventEntries) {
|
||||
entry.em.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 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
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.event.scheduler;
|
||||
|
||||
import config.YamlConfig;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import server.TimerManager;
|
||||
import net.server.Server;
|
||||
import net.server.audit.LockCollector;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import server.ThreadManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public class EventScriptScheduler {
|
||||
|
||||
private boolean disposed = false;
|
||||
private int idleProcs = 0;
|
||||
private Map<Runnable, Long> registeredEntries = new HashMap<>();
|
||||
|
||||
private ScheduledFuture<?> schedulerTask = null;
|
||||
private MonitoredReentrantLock schedulerLock;
|
||||
private Runnable monitorTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runBaseSchedule();
|
||||
}
|
||||
};
|
||||
|
||||
public EventScriptScheduler() {
|
||||
schedulerLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_SCHDL, true);
|
||||
}
|
||||
|
||||
private void runBaseSchedule() {
|
||||
List<Runnable> toRemove;
|
||||
Map<Runnable, Long> registeredEntriesCopy;
|
||||
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
if (registeredEntries.isEmpty()) {
|
||||
idleProcs++;
|
||||
|
||||
if (idleProcs >= YamlConfig.config.server.MOB_STATUS_MONITOR_LIFE) {
|
||||
if (schedulerTask != null) {
|
||||
schedulerTask.cancel(false);
|
||||
schedulerTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
idleProcs = 0;
|
||||
registeredEntriesCopy = new HashMap<>(registeredEntries);
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
|
||||
long timeNow = Server.getInstance().getCurrentTime();
|
||||
toRemove = new LinkedList<>();
|
||||
for (Entry<Runnable, Long> rmd : registeredEntriesCopy.entrySet()) {
|
||||
if (rmd.getValue() < timeNow) {
|
||||
Runnable r = rmd.getKey();
|
||||
|
||||
r.run(); // runs the scheduled action
|
||||
toRemove.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
for (Runnable r : toRemove) {
|
||||
registeredEntries.remove(r);
|
||||
}
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerEntry(final Runnable scheduledAction, final long duration) {
|
||||
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
idleProcs = 0;
|
||||
if (schedulerTask == null) {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
schedulerTask = TimerManager.getInstance().register(monitorTask, YamlConfig.config.server.MOB_STATUS_MONITOR_PROC, YamlConfig.config.server.MOB_STATUS_MONITOR_PROC);
|
||||
}
|
||||
|
||||
registeredEntries.put(scheduledAction, Server.getInstance().getCurrentTime() + duration);
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void cancelEntry(final Runnable scheduledAction) {
|
||||
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
registeredEntries.remove(scheduledAction);
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
if (schedulerTask != null) {
|
||||
schedulerTask.cancel(false);
|
||||
schedulerTask = null;
|
||||
}
|
||||
|
||||
registeredEntries.clear();
|
||||
disposed = true;
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
|
||||
disposeLocks();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void disposeLocks() {
|
||||
LockCollector.getInstance().registerDisposeAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
emptyLocks();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void emptyLocks() {
|
||||
schedulerLock = schedulerLock.dispose();
|
||||
}
|
||||
}
|
||||
39
src/main/java/scripting/item/ItemScriptManager.java
Normal file
39
src/main/java/scripting/item/ItemScriptManager.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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;
|
||||
|
||||
import client.MapleClient;
|
||||
import scripting.npc.NPCScriptManager;
|
||||
import server.MapleItemInformationProvider.ScriptedItem;
|
||||
|
||||
public class ItemScriptManager {
|
||||
|
||||
private static ItemScriptManager instance = new ItemScriptManager();
|
||||
|
||||
public static ItemScriptManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void runItemScript(MapleClient c, ScriptedItem scriptItem) {
|
||||
NPCScriptManager.getInstance().start(c, scriptItem, null);
|
||||
}
|
||||
}
|
||||
35
src/main/java/scripting/item/ItemScriptMethods.java
Normal file
35
src/main/java/scripting/item/ItemScriptMethods.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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;
|
||||
|
||||
import client.MapleClient;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kevintjuh93
|
||||
*/
|
||||
public class ItemScriptMethods extends AbstractPlayerInteraction {
|
||||
public ItemScriptMethods(MapleClient c) {
|
||||
super(c);
|
||||
}
|
||||
}
|
||||
94
src/main/java/scripting/map/MapScriptManager.java
Normal file
94
src/main/java/scripting/map/MapScriptManager.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.map;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import scripting.AbstractScriptManager;
|
||||
import tools.FilePrinter;
|
||||
|
||||
public class MapScriptManager extends AbstractScriptManager {
|
||||
|
||||
private static MapScriptManager instance = new MapScriptManager();
|
||||
|
||||
public static MapScriptManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Map<String, NashornScriptEngine> scripts = new HashMap<>();
|
||||
private ScriptEngineFactory sef;
|
||||
|
||||
private MapScriptManager() {
|
||||
ScriptEngineManager sem = new ScriptEngineManager();
|
||||
sef = sem.getEngineByName("javascript").getFactory();
|
||||
}
|
||||
|
||||
public void reloadScripts() {
|
||||
scripts.clear();
|
||||
}
|
||||
|
||||
public boolean runMapScript(MapleClient c, String mapScriptPath, boolean firstUser) {
|
||||
if (firstUser) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
int mapid = chr.getMapId();
|
||||
if (chr.hasEntered(mapScriptPath, mapid)) {
|
||||
return false;
|
||||
} else {
|
||||
chr.enteredScript(mapScriptPath, mapid);
|
||||
}
|
||||
}
|
||||
|
||||
NashornScriptEngine iv = scripts.get(mapScriptPath);
|
||||
if (iv != null) {
|
||||
try {
|
||||
iv.invokeFunction("start", new MapScriptMethods(c));
|
||||
return true;
|
||||
} catch (final ScriptException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
iv = getScriptEngine("map/" + mapScriptPath + ".js");
|
||||
if (iv == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scripts.put(mapScriptPath, iv);
|
||||
iv.invokeFunction("start", new MapScriptMethods(c));
|
||||
return true;
|
||||
} catch (final UndeclaredThrowableException | ScriptException ute) {
|
||||
FilePrinter.printError(FilePrinter.MAP_SCRIPT + mapScriptPath + ".txt", ute);
|
||||
} catch (final Exception e) {
|
||||
FilePrinter.printError(FilePrinter.MAP_SCRIPT + mapScriptPath + ".txt", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
169
src/main/java/scripting/map/MapScriptMethods.java
Normal file
169
src/main/java/scripting/map/MapScriptMethods.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.map;
|
||||
|
||||
import client.MapleCharacter.DelayedQuestUpdate;
|
||||
import client.MapleClient;
|
||||
import client.MapleQuestStatus;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import server.quest.MapleQuest;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
public class MapScriptMethods extends AbstractPlayerInteraction {
|
||||
|
||||
private String rewardstring = " title has been rewarded. Please see NPC Dalair to receive your Medal.";
|
||||
|
||||
public MapScriptMethods(MapleClient c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public void displayCygnusIntro() {
|
||||
switch (c.getPlayer().getMapId()) {
|
||||
case 913040100:
|
||||
lockUI();
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene0"));
|
||||
break;
|
||||
case 913040101:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene1"));
|
||||
break;
|
||||
case 913040102:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene2"));
|
||||
break;
|
||||
case 913040103:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene3"));
|
||||
break;
|
||||
case 913040104:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene4"));
|
||||
break;
|
||||
case 913040105:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene5"));
|
||||
break;
|
||||
case 913040106:
|
||||
lockUI();
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene6"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void displayAranIntro() {
|
||||
switch (c.getPlayer().getMapId()) {
|
||||
case 914090010:
|
||||
lockUI();
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction1.img/aranTutorial/Scene0"));
|
||||
break;
|
||||
case 914090011:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction1.img/aranTutorial/Scene1" + c.getPlayer().getGender()));
|
||||
break;
|
||||
case 914090012:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction1.img/aranTutorial/Scene2" + c.getPlayer().getGender()));
|
||||
break;
|
||||
case 914090013:
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction1.img/aranTutorial/Scene3"));
|
||||
break;
|
||||
case 914090100:
|
||||
lockUI();
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction1.img/aranTutorial/HandedPoleArm" + c.getPlayer().getGender()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void startExplorerExperience() {
|
||||
if (c.getPlayer().getMapId() == 1020100) //Swordman
|
||||
{
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction3.img/swordman/Scene" + c.getPlayer().getGender()));
|
||||
} else if (c.getPlayer().getMapId() == 1020200) //Magician
|
||||
{
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction3.img/magician/Scene" + c.getPlayer().getGender()));
|
||||
} else if (c.getPlayer().getMapId() == 1020300) //Archer
|
||||
{
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction3.img/archer/Scene" + c.getPlayer().getGender()));
|
||||
} else if (c.getPlayer().getMapId() == 1020400) //Rogue
|
||||
{
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction3.img/rogue/Scene" + c.getPlayer().getGender()));
|
||||
} else if (c.getPlayer().getMapId() == 1020500) //Pirate
|
||||
{
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction3.img/pirate/Scene" + c.getPlayer().getGender()));
|
||||
}
|
||||
}
|
||||
|
||||
public void goAdventure() {
|
||||
lockUI();
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction3.img/goAdventure/Scene" + c.getPlayer().getGender()));
|
||||
}
|
||||
|
||||
public void goLith() {
|
||||
lockUI();
|
||||
c.announce(MaplePacketCreator.showIntro("Effect/Direction3.img/goLith/Scene" + c.getPlayer().getGender()));
|
||||
}
|
||||
|
||||
public void explorerQuest(short questid, String questName) {
|
||||
MapleQuest quest = MapleQuest.getInstance(questid);
|
||||
if (!isQuestStarted(questid)) {
|
||||
if (!quest.forceStart(getPlayer(), 9000066)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
MapleQuestStatus qs = getPlayer().getQuest(quest);
|
||||
if (!qs.addMedalMap(getPlayer().getMapId())) {
|
||||
return;
|
||||
}
|
||||
String status = Integer.toString(qs.getMedalProgress());
|
||||
String infoex = qs.getInfoEx(0);
|
||||
getPlayer().announceUpdateQuest(DelayedQuestUpdate.UPDATE, qs, true);
|
||||
StringBuilder smp = new StringBuilder();
|
||||
StringBuilder etm = new StringBuilder();
|
||||
if (status.equals(infoex)) {
|
||||
etm.append("Earned the ").append(questName).append(" title!");
|
||||
smp.append("You have earned the <").append(questName).append(">").append(rewardstring);
|
||||
getPlayer().announce(MaplePacketCreator.getShowQuestCompletion(quest.getId()));
|
||||
} else {
|
||||
getPlayer().announce(MaplePacketCreator.earnTitleMessage(status + "/" + infoex + " regions explored."));
|
||||
etm.append("Trying for the ").append(questName).append(" title.");
|
||||
smp.append("You made progress on the ").append(questName).append(" title. ").append(status).append("/").append(infoex);
|
||||
}
|
||||
getPlayer().announce(MaplePacketCreator.earnTitleMessage(etm.toString()));
|
||||
showInfoText(smp.toString());
|
||||
}
|
||||
|
||||
public void touchTheSky() { //29004
|
||||
MapleQuest quest = MapleQuest.getInstance(29004);
|
||||
if (!isQuestStarted(29004)) {
|
||||
if (!quest.forceStart(getPlayer(), 9000066)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
MapleQuestStatus qs = getPlayer().getQuest(quest);
|
||||
if (!qs.addMedalMap(getPlayer().getMapId())) {
|
||||
return;
|
||||
}
|
||||
String status = Integer.toString(qs.getMedalProgress());
|
||||
getPlayer().announceUpdateQuest(DelayedQuestUpdate.UPDATE, qs, true);
|
||||
getPlayer().announce(MaplePacketCreator.earnTitleMessage(status + "/5 Completed"));
|
||||
getPlayer().announce(MaplePacketCreator.earnTitleMessage("The One Who's Touched the Sky title in progress."));
|
||||
if (Integer.toString(qs.getMedalProgress()).equals(qs.getInfoEx(0))) {
|
||||
showInfoText("The One Who's Touched the Sky" + rewardstring);
|
||||
getPlayer().announce(MaplePacketCreator.getShowQuestCompletion(quest.getId()));
|
||||
} else {
|
||||
showInfoText("The One Who's Touched the Sky title in progress. " + status + "/5 Completed");
|
||||
}
|
||||
}
|
||||
}
|
||||
1161
src/main/java/scripting/npc/NPCConversationManager.java
Normal file
1161
src/main/java/scripting/npc/NPCConversationManager.java
Normal file
File diff suppressed because it is too large
Load Diff
216
src/main/java/scripting/npc/NPCScriptManager.java
Normal file
216
src/main/java/scripting/npc/NPCScriptManager.java
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.npc;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import net.server.world.MaplePartyCharacter;
|
||||
|
||||
import scripting.AbstractScriptManager;
|
||||
import server.MapleItemInformationProvider.ScriptedItem;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public class NPCScriptManager extends AbstractScriptManager {
|
||||
|
||||
private static NPCScriptManager instance = new NPCScriptManager();
|
||||
|
||||
public static NPCScriptManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Map<MapleClient, NPCConversationManager> cms = new HashMap<>();
|
||||
private Map<MapleClient, NashornScriptEngine> scripts = new HashMap<>();
|
||||
|
||||
public boolean isNpcScriptAvailable(MapleClient c, String fileName) {
|
||||
NashornScriptEngine iv = null;
|
||||
if (fileName != null) {
|
||||
iv = getScriptEngine("npc/" + fileName + ".js", c);
|
||||
}
|
||||
|
||||
return iv != null;
|
||||
}
|
||||
|
||||
public boolean start(MapleClient c, int npc, MapleCharacter chr) {
|
||||
return start(c, npc, -1, chr);
|
||||
}
|
||||
|
||||
public boolean start(MapleClient c, int npc, int oid, MapleCharacter chr) {
|
||||
return start(c, npc, oid, null, chr);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
public void start(String filename, MapleClient c, int npc, List<MaplePartyCharacter> chrs) {
|
||||
try {
|
||||
NPCConversationManager cm = new NPCConversationManager(c, npc, chrs, true);
|
||||
cm.dispose();
|
||||
if (cms.containsKey(c)) {
|
||||
return;
|
||||
}
|
||||
cms.put(c, cm);
|
||||
NashornScriptEngine iv = getScriptEngine("npc/" + filename + ".js", c);
|
||||
|
||||
if (iv == null) {
|
||||
c.getPlayer().dropMessage(1, "NPC " + npc + " is uncoded.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
iv.put("cm", cm);
|
||||
scripts.put(c, iv);
|
||||
try {
|
||||
iv.invokeFunction("start", chrs);
|
||||
} catch (final NoSuchMethodException nsme) {
|
||||
nsme.printStackTrace();
|
||||
}
|
||||
|
||||
} catch (final UndeclaredThrowableException ute) {
|
||||
FilePrinter.printError(FilePrinter.NPC + npc + ".txt", ute);
|
||||
dispose(c);
|
||||
} catch (final Exception e) {
|
||||
FilePrinter.printError(FilePrinter.NPC + npc + ".txt", e);
|
||||
dispose(c);
|
||||
}
|
||||
}
|
||||
|
||||
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, itemScript);
|
||||
if (cms.containsKey(c)) {
|
||||
dispose(c);
|
||||
}
|
||||
if (c.canClickNPC()) {
|
||||
cms.put(c, cm);
|
||||
NashornScriptEngine iv = null;
|
||||
if (!itemScript) {
|
||||
if (fileName != null) {
|
||||
iv = getScriptEngine("npc/" + fileName + ".js", c);
|
||||
}
|
||||
} else {
|
||||
if (fileName != null) { // thanks MiLin for drafting NPC-based item scripts
|
||||
iv = getScriptEngine("item/" + fileName + ".js", c);
|
||||
}
|
||||
}
|
||||
if (iv == null) {
|
||||
iv = getScriptEngine("npc/" + npc + ".js", c);
|
||||
cm.resetItemScript();
|
||||
}
|
||||
if (iv == null) {
|
||||
dispose(c);
|
||||
return false;
|
||||
}
|
||||
iv.put(engineName, cm);
|
||||
scripts.put(c, iv);
|
||||
c.setClickedNPC();
|
||||
try {
|
||||
iv.invokeFunction("start");
|
||||
} catch (final NoSuchMethodException nsme) {
|
||||
try {
|
||||
iv.invokeFunction("start", chr);
|
||||
} catch (final NoSuchMethodException nsma) {
|
||||
nsma.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
return true;
|
||||
} catch (final UndeclaredThrowableException | ScriptException ute) {
|
||||
FilePrinter.printError(FilePrinter.NPC + npc + ".txt", ute);
|
||||
dispose(c);
|
||||
|
||||
return false;
|
||||
} catch (final Exception e) {
|
||||
FilePrinter.printError(FilePrinter.NPC + npc + ".txt", e);
|
||||
dispose(c);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void action(MapleClient c, byte mode, byte type, int selection) {
|
||||
NashornScriptEngine iv = scripts.get(c);
|
||||
if (iv != null) {
|
||||
try {
|
||||
c.setClickedNPC();
|
||||
iv.invokeFunction("action", mode, type, selection);
|
||||
} catch (ScriptException | NoSuchMethodException t) {
|
||||
if (getCM(c) != null) {
|
||||
FilePrinter.printError(FilePrinter.NPC + getCM(c).getNpc() + ".txt", t);
|
||||
}
|
||||
dispose(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose(NPCConversationManager cm) {
|
||||
MapleClient c = cm.getClient();
|
||||
c.getPlayer().setCS(false);
|
||||
c.getPlayer().setNpcCooldown(System.currentTimeMillis());
|
||||
cms.remove(c);
|
||||
scripts.remove(c);
|
||||
|
||||
String scriptFolder = (cm.isItemScript() ? "item" : "npc");
|
||||
if (cm.getScriptName() != null) {
|
||||
resetContext(scriptFolder + "/" + cm.getScriptName() + ".js", c);
|
||||
} else {
|
||||
resetContext(scriptFolder + "/" + cm.getNpc() + ".js", c);
|
||||
}
|
||||
|
||||
c.getPlayer().flushDelayedUpdateQuests();
|
||||
}
|
||||
|
||||
public void dispose(MapleClient c) {
|
||||
NPCConversationManager cm = cms.get(c);
|
||||
if (cm != null) {
|
||||
dispose(cm);
|
||||
}
|
||||
}
|
||||
|
||||
public NPCConversationManager getCM(MapleClient c) {
|
||||
return cms.get(c);
|
||||
}
|
||||
|
||||
}
|
||||
101
src/main/java/scripting/portal/PortalPlayerInteraction.java
Normal file
101
src/main/java/scripting/portal/PortalPlayerInteraction.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.portal;
|
||||
|
||||
import client.MapleClient;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import scripting.map.MapScriptManager;
|
||||
import server.maps.MaplePortal;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
public class PortalPlayerInteraction extends AbstractPlayerInteraction {
|
||||
|
||||
private MaplePortal portal;
|
||||
|
||||
public PortalPlayerInteraction(MapleClient c, MaplePortal portal) {
|
||||
super(c);
|
||||
this.portal = portal;
|
||||
}
|
||||
|
||||
public MaplePortal getPortal() {
|
||||
return portal;
|
||||
}
|
||||
|
||||
public void runMapScript() {
|
||||
MapScriptManager msm = MapScriptManager.getInstance();
|
||||
msm.runMapScript(c, "onUserEnter/" + portal.getScriptName(), false);
|
||||
}
|
||||
|
||||
public boolean hasLevel30Character() {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
Connection con = null;
|
||||
try {
|
||||
con = DatabaseConnection.getConnection();
|
||||
ps = con.prepareStatement("SELECT `level` FROM `characters` WHERE accountid = ?");
|
||||
ps.setInt(1, getPlayer().getAccountID());
|
||||
rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
if (rs.getInt("level") >= 30) {
|
||||
ps.close();
|
||||
rs.close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (ps != null && !ps.isClosed()) {
|
||||
ps.close();
|
||||
}
|
||||
if (rs != null && !rs.isClosed()) {
|
||||
rs.close();
|
||||
}
|
||||
if (con != null && !con.isClosed()) {
|
||||
con.close();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return getPlayer().getLevel() >= 30;
|
||||
}
|
||||
|
||||
public void blockPortal() {
|
||||
c.getPlayer().blockPortal(getPortal().getScriptName());
|
||||
}
|
||||
|
||||
public void unblockPortal() {
|
||||
c.getPlayer().unblockPortal(getPortal().getScriptName());
|
||||
}
|
||||
|
||||
public void playPortalSound() {
|
||||
c.announce(MaplePacketCreator.playPortalSound());
|
||||
}
|
||||
}
|
||||
26
src/main/java/scripting/portal/PortalScript.java
Normal file
26
src/main/java/scripting/portal/PortalScript.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.portal;
|
||||
|
||||
public interface PortalScript {
|
||||
public boolean enter(PortalPlayerInteraction ppi);
|
||||
}
|
||||
85
src/main/java/scripting/portal/PortalScriptManager.java
Normal file
85
src/main/java/scripting/portal/PortalScriptManager.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.portal;
|
||||
|
||||
import client.MapleClient;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import scripting.AbstractScriptManager;
|
||||
import server.maps.MaplePortal;
|
||||
import tools.FilePrinter;
|
||||
|
||||
public class PortalScriptManager extends AbstractScriptManager {
|
||||
|
||||
private static PortalScriptManager instance = new PortalScriptManager();
|
||||
|
||||
public static PortalScriptManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Map<String, NashornScriptEngine> scripts = new HashMap<>();
|
||||
private ScriptEngineFactory sef;
|
||||
|
||||
private PortalScriptManager() {
|
||||
ScriptEngineManager sem = new ScriptEngineManager();
|
||||
sef = sem.getEngineByName("javascript").getFactory();
|
||||
}
|
||||
|
||||
private NashornScriptEngine getPortalScript(String scriptName) {
|
||||
String scriptPath = "portal/" + scriptName + ".js";
|
||||
NashornScriptEngine iv = scripts.get(scriptPath);
|
||||
if (iv != null) {
|
||||
return iv;
|
||||
}
|
||||
|
||||
iv = getScriptEngine(scriptPath);
|
||||
if (iv == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
scripts.put(scriptPath, iv);
|
||||
return iv;
|
||||
}
|
||||
|
||||
public boolean executePortalScript(MaplePortal portal, MapleClient c) {
|
||||
try {
|
||||
NashornScriptEngine iv = getPortalScript(portal.getScriptName());
|
||||
if (iv != null) {
|
||||
boolean couldWarp = (boolean) iv.invokeFunction("enter", new PortalPlayerInteraction(c, portal));
|
||||
return couldWarp;
|
||||
}
|
||||
} catch (UndeclaredThrowableException ute) {
|
||||
FilePrinter.printError(FilePrinter.PORTAL + portal.getScriptName() + ".txt", ute);
|
||||
} catch (final Exception e) {
|
||||
FilePrinter.printError(FilePrinter.PORTAL + portal.getScriptName() + ".txt", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reloadPortalScripts() {
|
||||
scripts.clear();
|
||||
}
|
||||
}
|
||||
90
src/main/java/scripting/quest/QuestActionManager.java
Normal file
90
src/main/java/scripting/quest/QuestActionManager.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.quest;
|
||||
|
||||
import client.MapleClient;
|
||||
import scripting.npc.NPCConversationManager;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.quest.MapleQuest;
|
||||
import server.quest.actions.ExpAction;
|
||||
import server.quest.actions.MesoAction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RMZero213
|
||||
*/
|
||||
public class QuestActionManager extends NPCConversationManager {
|
||||
private boolean start; // this is if the script in question is start or end
|
||||
private int quest;
|
||||
|
||||
public QuestActionManager(MapleClient c, int quest, int npc, boolean start) {
|
||||
super(c, npc, null);
|
||||
this.quest = quest;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public int getQuest() {
|
||||
return quest;
|
||||
}
|
||||
|
||||
public boolean isStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
QuestScriptManager.getInstance().dispose(this, getClient());
|
||||
}
|
||||
|
||||
public boolean forceStartQuest() {
|
||||
return forceStartQuest(quest);
|
||||
}
|
||||
|
||||
public boolean forceCompleteQuest() {
|
||||
return forceCompleteQuest(quest);
|
||||
}
|
||||
|
||||
// For compatibility with some older scripts...
|
||||
public void startQuest() {
|
||||
forceStartQuest();
|
||||
}
|
||||
|
||||
// For compatibility with some older scripts...
|
||||
public void completeQuest() {
|
||||
forceCompleteQuest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gainExp(int gain) {
|
||||
ExpAction.runAction(getPlayer(), gain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gainMeso(int gain) {
|
||||
MesoAction.runAction(getPlayer(), gain);
|
||||
}
|
||||
|
||||
public String getMedalName() { // usable only for medal quests (id 299XX)
|
||||
MapleQuest q = MapleQuest.getInstance(quest);
|
||||
return MapleItemInformationProvider.getInstance().getName(q.getMedalRequirement());
|
||||
}
|
||||
}
|
||||
221
src/main/java/scripting/quest/QuestScriptManager.java
Normal file
221
src/main/java/scripting/quest/QuestScriptManager.java
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.quest;
|
||||
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import scripting.AbstractScriptManager;
|
||||
import server.quest.MapleQuest;
|
||||
import tools.FilePrinter;
|
||||
import constants.game.GameConstants;
|
||||
import client.MapleClient;
|
||||
import client.MapleQuestStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RMZero213
|
||||
*/
|
||||
public class QuestScriptManager extends AbstractScriptManager {
|
||||
|
||||
private static QuestScriptManager instance = new QuestScriptManager();
|
||||
|
||||
public static QuestScriptManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Map<MapleClient, QuestActionManager> qms = new HashMap<>();
|
||||
private Map<MapleClient, NashornScriptEngine> scripts = new HashMap<>();
|
||||
|
||||
private NashornScriptEngine getQuestScriptEngine(MapleClient c, short questid) {
|
||||
NashornScriptEngine iv = getScriptEngine("quest/" + questid + ".js", c);
|
||||
if (iv == null && GameConstants.isMedalQuest(questid)) {
|
||||
iv = getScriptEngine("quest/medalQuest.js", c); // start generic medal quest
|
||||
}
|
||||
|
||||
return iv;
|
||||
}
|
||||
|
||||
public void start(MapleClient c, short questid, int npc) {
|
||||
MapleQuest quest = MapleQuest.getInstance(questid);
|
||||
try {
|
||||
QuestActionManager qm = new QuestActionManager(c, questid, npc, true);
|
||||
if (qms.containsKey(c)) {
|
||||
return;
|
||||
}
|
||||
if(c.canClickNPC()) {
|
||||
qms.put(c, qm);
|
||||
|
||||
if (!quest.hasScriptRequirement(false)) { // lack of scripted quest checks found thanks to Mali, Resinate
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
NashornScriptEngine iv = getQuestScriptEngine(c, questid);
|
||||
if (iv == null) {
|
||||
FilePrinter.printError(FilePrinter.QUEST_UNCODED, "START Quest " + questid + " is uncoded.");
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
iv.put("qm", qm);
|
||||
scripts.put(c, iv);
|
||||
c.setClickedNPC();
|
||||
iv.invokeFunction("start", (byte) 1, (byte) 0, 0);
|
||||
}
|
||||
} catch (final UndeclaredThrowableException ute) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + questid + ".txt", ute);
|
||||
dispose(c);
|
||||
} catch (final Throwable t) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + getQM(c).getQuest() + ".txt", t);
|
||||
dispose(c);
|
||||
}
|
||||
}
|
||||
|
||||
public void start(MapleClient c, byte mode, byte type, int selection) {
|
||||
NashornScriptEngine iv = scripts.get(c);
|
||||
if (iv != null) {
|
||||
try {
|
||||
c.setClickedNPC();
|
||||
iv.invokeFunction("start", mode, type, selection);
|
||||
} catch (final UndeclaredThrowableException ute) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + getQM(c).getQuest() + ".txt", ute);
|
||||
dispose(c);
|
||||
} catch (final Throwable t) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + getQM(c).getQuest() + ".txt", t);
|
||||
dispose(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void end(MapleClient c, short questid, int npc) {
|
||||
MapleQuest quest = MapleQuest.getInstance(questid);
|
||||
if (!c.getPlayer().getQuest(quest).getStatus().equals(MapleQuestStatus.Status.STARTED) || !c.getPlayer().getMap().containsNPC(npc)) {
|
||||
dispose(c);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
QuestActionManager qm = new QuestActionManager(c, questid, npc, false);
|
||||
if (qms.containsKey(c)) {
|
||||
return;
|
||||
}
|
||||
if(c.canClickNPC()){
|
||||
qms.put(c, qm);
|
||||
|
||||
if (!quest.hasScriptRequirement(true)) {
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
NashornScriptEngine iv = getQuestScriptEngine(c, questid);
|
||||
if (iv == null) {
|
||||
FilePrinter.printError(FilePrinter.QUEST_UNCODED, "END Quest " + questid + " is uncoded.");
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
iv.put("qm", qm);
|
||||
scripts.put(c, iv);
|
||||
c.setClickedNPC();
|
||||
iv.invokeFunction("end", (byte) 1, (byte) 0, 0);
|
||||
}
|
||||
} catch (final UndeclaredThrowableException ute) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + questid + ".txt", ute);
|
||||
dispose(c);
|
||||
} catch (final Throwable t) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + getQM(c).getQuest() + ".txt", t);
|
||||
dispose(c);
|
||||
}
|
||||
}
|
||||
|
||||
public void end(MapleClient c, byte mode, byte type, int selection) {
|
||||
NashornScriptEngine iv = scripts.get(c);
|
||||
if (iv != null) {
|
||||
try {
|
||||
c.setClickedNPC();
|
||||
iv.invokeFunction("end", mode, type, selection);
|
||||
} catch (final UndeclaredThrowableException ute) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + getQM(c).getQuest() + ".txt", ute);
|
||||
dispose(c);
|
||||
} catch (final Throwable t) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + getQM(c).getQuest() + ".txt", t);
|
||||
dispose(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void raiseOpen(MapleClient c, short questid, int npc) {
|
||||
try {
|
||||
QuestActionManager qm = new QuestActionManager(c, questid, npc, true);
|
||||
if (qms.containsKey(c)) {
|
||||
return;
|
||||
}
|
||||
if(c.canClickNPC()) {
|
||||
qms.put(c, qm);
|
||||
|
||||
NashornScriptEngine iv = getQuestScriptEngine(c, questid);
|
||||
if (iv == null) {
|
||||
//FilePrinter.printError(FilePrinter.QUEST_UNCODED, "RAISE Quest " + questid + " is uncoded.");
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
iv.put("qm", qm);
|
||||
scripts.put(c, iv);
|
||||
c.setClickedNPC();
|
||||
iv.invokeFunction("raiseOpen");
|
||||
}
|
||||
} catch (final UndeclaredThrowableException ute) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + questid + ".txt", ute);
|
||||
dispose(c);
|
||||
} catch (final Throwable t) {
|
||||
FilePrinter.printError(FilePrinter.QUEST + getQM(c).getQuest() + ".txt", t);
|
||||
dispose(c);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose(QuestActionManager qm, MapleClient c) {
|
||||
qms.remove(c);
|
||||
scripts.remove(c);
|
||||
c.getPlayer().setNpcCooldown(System.currentTimeMillis());
|
||||
resetContext("quest/" + qm.getQuest() + ".js", c);
|
||||
c.getPlayer().flushDelayedUpdateQuests();
|
||||
}
|
||||
|
||||
public void dispose(MapleClient c) {
|
||||
QuestActionManager qm = qms.get(c);
|
||||
if (qm != null) {
|
||||
dispose(qm, c);
|
||||
}
|
||||
}
|
||||
|
||||
public QuestActionManager getQM(MapleClient c) {
|
||||
return qms.get(c);
|
||||
}
|
||||
|
||||
public void reloadQuestScripts() {
|
||||
scripts.clear();
|
||||
qms.clear();
|
||||
}
|
||||
}
|
||||
362
src/main/java/scripting/reactor/ReactorActionManager.java
Normal file
362
src/main/java/scripting/reactor/ReactorActionManager.java
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.reactor;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import config.YamlConfig;
|
||||
import constants.inventory.ItemConstants;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.script.ScriptException;
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import scripting.event.EventManager;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.TimerManager;
|
||||
import server.life.MapleLifeFactory;
|
||||
import server.life.MapleMonster;
|
||||
import server.maps.MapMonitor;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.MapleReactor;
|
||||
import server.maps.ReactorDropEntry;
|
||||
import server.partyquest.MapleCarnivalFactory;
|
||||
import server.partyquest.MapleCarnivalFactory.MCSkill;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
* @author Lerk
|
||||
* @author Ronan
|
||||
*/
|
||||
public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
private MapleReactor reactor;
|
||||
private NashornScriptEngine iv;
|
||||
private ScheduledFuture<?> sprayTask = null;
|
||||
|
||||
public ReactorActionManager(MapleClient c, MapleReactor reactor, NashornScriptEngine iv) {
|
||||
super(c);
|
||||
this.reactor = reactor;
|
||||
this.iv = iv;
|
||||
}
|
||||
|
||||
public void hitReactor() {
|
||||
reactor.hitReactor(c);
|
||||
}
|
||||
|
||||
public void destroyNpc(int npcId) {
|
||||
reactor.getMap().destroyNPC(npcId);
|
||||
}
|
||||
|
||||
private static void sortDropEntries(List<ReactorDropEntry> from, List<ReactorDropEntry> item, List<ReactorDropEntry> visibleQuest, List<ReactorDropEntry> otherQuest, MapleCharacter chr) {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
for(ReactorDropEntry mde : from) {
|
||||
if(!ii.isQuestItem(mde.itemId)) {
|
||||
item.add(mde);
|
||||
} else {
|
||||
if(chr.needQuestItem(mde.questid, mde.itemId)) {
|
||||
visibleQuest.add(mde);
|
||||
} else {
|
||||
otherQuest.add(mde);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ReactorDropEntry> assembleReactorDropEntries(MapleCharacter chr, List<ReactorDropEntry> items) {
|
||||
final List<ReactorDropEntry> dropEntry = new ArrayList<>();
|
||||
final List<ReactorDropEntry> visibleQuestEntry = new ArrayList<>();
|
||||
final List<ReactorDropEntry> otherQuestEntry = new ArrayList<>();
|
||||
sortDropEntries(items, dropEntry, visibleQuestEntry, otherQuestEntry, chr);
|
||||
|
||||
Collections.shuffle(dropEntry);
|
||||
Collections.shuffle(visibleQuestEntry);
|
||||
Collections.shuffle(otherQuestEntry);
|
||||
|
||||
items.clear();
|
||||
items.addAll(dropEntry);
|
||||
items.addAll(visibleQuestEntry);
|
||||
items.addAll(otherQuestEntry);
|
||||
|
||||
List<ReactorDropEntry> items1 = new ArrayList<>(items.size());
|
||||
List<ReactorDropEntry> items2 = new ArrayList<>(items.size() / 2);
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (i % 2 == 0) {
|
||||
items1.add(items.get(i));
|
||||
} else {
|
||||
items2.add(items.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
Collections.reverse(items1);
|
||||
items1.addAll(items2);
|
||||
|
||||
return items1;
|
||||
}
|
||||
|
||||
public void sprayItems() {
|
||||
sprayItems(false, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void sprayItems(boolean meso, int mesoChance, int minMeso, int maxMeso) {
|
||||
sprayItems(meso, mesoChance, minMeso, maxMeso, 0);
|
||||
}
|
||||
|
||||
public void sprayItems(boolean meso, int mesoChance, int minMeso, int maxMeso, int minItems) {
|
||||
sprayItems((int)reactor.getPosition().getX(), (int)reactor.getPosition().getY(), meso, mesoChance, minMeso, maxMeso, minItems);
|
||||
}
|
||||
|
||||
public void sprayItems(int posX, int posY, boolean meso, int mesoChance, int minMeso, int maxMeso, int minItems) {
|
||||
dropItems(true, posX, posY, meso, mesoChance, minMeso, maxMeso, minItems);
|
||||
}
|
||||
|
||||
public void dropItems() {
|
||||
dropItems(false, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void dropItems(boolean meso, int mesoChance, int minMeso, int maxMeso) {
|
||||
dropItems(meso, mesoChance, minMeso, maxMeso, 0);
|
||||
}
|
||||
|
||||
public void dropItems(boolean meso, int mesoChance, int minMeso, int maxMeso, int minItems) {
|
||||
dropItems((int)reactor.getPosition().getX(), (int)reactor.getPosition().getY(), meso, mesoChance, minMeso, maxMeso, minItems);
|
||||
}
|
||||
|
||||
public void dropItems(int posX, int posY, boolean meso, int mesoChance, int minMeso, int maxMeso, int minItems) {
|
||||
dropItems(true, posX, posY, meso, mesoChance, minMeso, maxMeso, minItems); // all reactors actually drop items sequentially... thanks inhyuk for pointing this out!
|
||||
}
|
||||
|
||||
public void dropItems(boolean delayed, int posX, int posY, boolean meso, int mesoChance, final int minMeso, final int maxMeso, int minItems) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
if(chr == null) return;
|
||||
|
||||
List<ReactorDropEntry> items = assembleReactorDropEntries(chr, generateDropList(getDropChances(), chr.getDropRate(), meso, mesoChance, minItems));
|
||||
if(items.size() % 2 == 0) posX -= 12;
|
||||
final Point dropPos = new Point(posX, posY);
|
||||
|
||||
if(!delayed) {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
byte p = 1;
|
||||
for (ReactorDropEntry d : items) {
|
||||
dropPos.x = (int) (posX + ((p % 2 == 0) ? (25 * ((p + 1) / 2)) : -(25 * (p / 2))));
|
||||
p++;
|
||||
|
||||
if (d.itemId == 0) {
|
||||
int range = maxMeso - minMeso;
|
||||
int displayDrop = (int) (Math.random() * range) + minMeso;
|
||||
int mesoDrop = (displayDrop * c.getWorldServer().getMesoRate());
|
||||
reactor.getMap().spawnMesoDrop(mesoDrop, reactor.getMap().calcDropPos(dropPos, reactor.getPosition()), reactor, c.getPlayer(), false, (byte) 2);
|
||||
} else {
|
||||
Item drop;
|
||||
|
||||
if (ItemConstants.getInventoryType(d.itemId) != MapleInventoryType.EQUIP) {
|
||||
drop = new Item(d.itemId, (short) 0, (short) 1);
|
||||
} else {
|
||||
drop = ii.randomizeStats((Equip) ii.getEquipById(d.itemId));
|
||||
}
|
||||
|
||||
reactor.getMap().dropFromReactor(getPlayer(), reactor, drop, dropPos, (short) d.questid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final MapleReactor r = reactor;
|
||||
final List<ReactorDropEntry> dropItems = items;
|
||||
final int worldMesoRate = c.getWorldServer().getMesoRate();
|
||||
|
||||
dropPos.x -= (12 * items.size());
|
||||
|
||||
sprayTask = TimerManager.getInstance().register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(dropItems.isEmpty()) {
|
||||
sprayTask.cancel(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ReactorDropEntry d = dropItems.remove(0);
|
||||
if (d.itemId == 0) {
|
||||
int range = maxMeso - minMeso;
|
||||
int displayDrop = (int) (Math.random() * range) + minMeso;
|
||||
int mesoDrop = (displayDrop * worldMesoRate);
|
||||
r.getMap().spawnMesoDrop(mesoDrop, r.getMap().calcDropPos(dropPos, r.getPosition()), r, chr, false, (byte) 2);
|
||||
} else {
|
||||
Item drop;
|
||||
|
||||
if (ItemConstants.getInventoryType(d.itemId) != MapleInventoryType.EQUIP) {
|
||||
drop = new Item(d.itemId, (short) 0, (short) 1);
|
||||
} else {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
drop = ii.randomizeStats((Equip) ii.getEquipById(d.itemId));
|
||||
}
|
||||
|
||||
r.getMap().dropFromReactor(getPlayer(), r, drop, dropPos, (short) d.questid);
|
||||
}
|
||||
|
||||
dropPos.x += 25;
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ReactorDropEntry> getDropChances() {
|
||||
return ReactorScriptManager.getInstance().getDrops(reactor.getId());
|
||||
}
|
||||
|
||||
private List<ReactorDropEntry> generateDropList(List<ReactorDropEntry> drops, int dropRate, boolean meso, int mesoChance, int minItems) {
|
||||
List<ReactorDropEntry> items = new ArrayList<>();
|
||||
if (meso && Math.random() < (1 / (double) mesoChance)) {
|
||||
items.add(new ReactorDropEntry(0, mesoChance, -1));
|
||||
}
|
||||
|
||||
for(ReactorDropEntry mde : drops) {
|
||||
if (Math.random() < (dropRate / (double) mde.chance)) {
|
||||
items.add(mde);
|
||||
}
|
||||
}
|
||||
|
||||
while (items.size() < minItems) {
|
||||
items.add(new ReactorDropEntry(0, mesoChance, -1));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public void spawnMonster(int id) {
|
||||
spawnMonster(id, 1, getPosition());
|
||||
}
|
||||
|
||||
public void createMapMonitor(int mapId, String portal) {
|
||||
new MapMonitor(c.getChannelServer().getMapFactory().getMap(mapId), portal);
|
||||
}
|
||||
|
||||
public void spawnMonster(int id, int qty) {
|
||||
spawnMonster(id, qty, getPosition());
|
||||
}
|
||||
|
||||
public void spawnMonster(int id, int qty, int x, int y) {
|
||||
spawnMonster(id, qty, new Point(x, y));
|
||||
}
|
||||
|
||||
public void spawnMonster(int id, int qty, Point pos) {
|
||||
for (int i = 0; i < qty; i++) {
|
||||
reactor.getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(id), pos);
|
||||
}
|
||||
}
|
||||
|
||||
public Point getPosition() {
|
||||
Point pos = reactor.getPosition();
|
||||
pos.y -= 10;
|
||||
return pos;
|
||||
}
|
||||
|
||||
public void spawnNpc(int npcId) {
|
||||
spawnNpc(npcId, getPosition());
|
||||
}
|
||||
|
||||
public void spawnNpc(int npcId, Point pos) {
|
||||
spawnNpc(npcId, pos, reactor.getMap());
|
||||
}
|
||||
|
||||
public void hitMonsterWithReactor(int id, int hitsToKill) { // until someone comes with a better solution, why not?
|
||||
int customTime = YamlConfig.config.server.MOB_REACTOR_REFRESH_TIME;
|
||||
if(customTime > 0) {
|
||||
reactor.setDelay(customTime);
|
||||
}
|
||||
|
||||
MapleMap map = reactor.getMap();
|
||||
MapleMonster mm = map.getMonsterById(id);
|
||||
if(mm != null) {
|
||||
int damage = (int)Math.ceil(mm.getMaxHp() / hitsToKill);
|
||||
MapleCharacter chr = this.getPlayer();
|
||||
|
||||
if(chr != null) {
|
||||
map.damageMonster(chr, mm, damage);
|
||||
map.broadcastMessage(MaplePacketCreator.damageMonster(mm.getObjectId(), damage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MapleReactor getReactor() {
|
||||
return reactor;
|
||||
}
|
||||
|
||||
public void spawnFakeMonster(int id) {
|
||||
reactor.getMap().spawnFakeMonsterOnGroundBelow(MapleLifeFactory.getMonster(id), getPosition());
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> schedule(String methodName, long delay) {
|
||||
return schedule(methodName, null, delay);
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> schedule(final String methodName, final EventInstanceManager eim, long delay) {
|
||||
return TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
iv.invokeFunction(methodName, eim);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> scheduleAtTimestamp(final String methodName, long timestamp) {
|
||||
return TimerManager.getInstance().scheduleAtTimestamp(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
iv.invokeFunction(methodName, (Object) null);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}, timestamp);
|
||||
}
|
||||
|
||||
public void dispelAllMonsters(int num, int team) { //dispels all mobs, cpq
|
||||
final MCSkill skil = MapleCarnivalFactory.getInstance().getGuardian(num);
|
||||
if (skil != null) {
|
||||
for (MapleMonster mons : getMap().getAllMonsters()) {
|
||||
if(mons.getTeam() == team) {
|
||||
mons.dispelSkill(skil.getSkill());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (team == 0) {
|
||||
getPlayer().getMap().getRedTeamBuffs().remove(skil);
|
||||
} else {
|
||||
getPlayer().getMap().getBlueTeamBuffs().remove(skil);
|
||||
}
|
||||
}
|
||||
}
|
||||
134
src/main/java/scripting/reactor/ReactorScriptManager.java
Normal file
134
src/main/java/scripting/reactor/ReactorScriptManager.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
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 program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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.reactor;
|
||||
|
||||
import client.MapleClient;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngine;
|
||||
import scripting.AbstractScriptManager;
|
||||
import server.maps.MapleReactor;
|
||||
import server.maps.ReactorDropEntry;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.FilePrinter;
|
||||
|
||||
/**
|
||||
* @author Lerk
|
||||
*/
|
||||
public class ReactorScriptManager extends AbstractScriptManager {
|
||||
|
||||
private static ReactorScriptManager instance = new ReactorScriptManager();
|
||||
|
||||
public static ReactorScriptManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Map<Integer, List<ReactorDropEntry>> drops = new HashMap<>();
|
||||
|
||||
public void onHit(MapleClient c, MapleReactor reactor) {
|
||||
try {
|
||||
NashornScriptEngine iv = getScriptEngine("reactor/" + reactor.getId() + ".js", c);
|
||||
if (iv == null) return;
|
||||
|
||||
ReactorActionManager rm = new ReactorActionManager(c, reactor, iv);
|
||||
iv.put("rm", rm);
|
||||
iv.invokeFunction("hit");
|
||||
} catch (final NoSuchMethodException e) {} //do nothing, hit is OPTIONAL
|
||||
|
||||
catch (final ScriptException | NullPointerException e) {
|
||||
FilePrinter.printError(FilePrinter.REACTOR + reactor.getId() + ".txt", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void act(MapleClient c, MapleReactor reactor) {
|
||||
try {
|
||||
NashornScriptEngine iv = getScriptEngine("reactor/" + reactor.getId() + ".js", c);
|
||||
if (iv == null) return;
|
||||
|
||||
ReactorActionManager rm = new ReactorActionManager(c, reactor, iv);
|
||||
iv.put("rm", rm);
|
||||
iv.invokeFunction("act");
|
||||
} catch (final ScriptException | NoSuchMethodException | NullPointerException e) {
|
||||
FilePrinter.printError(FilePrinter.REACTOR + reactor.getId() + ".txt", e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ReactorDropEntry> getDrops(int rid) {
|
||||
List<ReactorDropEntry> ret = drops.get(rid);
|
||||
if (ret == null) {
|
||||
ret = new LinkedList<>();
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT itemid, chance, questid FROM reactordrops WHERE reactorid = ? AND chance >= 0")) {
|
||||
ps.setInt(1, rid);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
ret.add(new ReactorDropEntry(rs.getInt("itemid"), rs.getInt("chance"), rs.getInt("questid")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
con.close();
|
||||
} catch (Throwable e) {
|
||||
FilePrinter.printError(FilePrinter.REACTOR + rid + ".txt", e);
|
||||
}
|
||||
drops.put(rid, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void clearDrops() {
|
||||
drops.clear();
|
||||
}
|
||||
|
||||
public void touch(MapleClient c, MapleReactor reactor) {
|
||||
touching(c, reactor, true);
|
||||
}
|
||||
|
||||
public void untouch(MapleClient c, MapleReactor reactor) {
|
||||
touching(c, reactor, false);
|
||||
}
|
||||
|
||||
private void touching(MapleClient c, MapleReactor reactor, boolean touching) {
|
||||
try {
|
||||
NashornScriptEngine iv = getScriptEngine("reactor/" + reactor.getId() + ".js", c);
|
||||
if (iv == null) return;
|
||||
|
||||
ReactorActionManager rm = new ReactorActionManager(c, reactor, iv);
|
||||
iv.put("rm", rm);
|
||||
if (touching) {
|
||||
iv.invokeFunction("touch");
|
||||
} else {
|
||||
iv.invokeFunction("untouch");
|
||||
}
|
||||
} catch (final ScriptException | NoSuchMethodException | NullPointerException ute) {
|
||||
FilePrinter.printError(FilePrinter.REACTOR + reactor.getId() + ".txt", ute);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user