Files
sweetgum-server/src/scripting/event/EventManager.java
ronancpl a56312ddd3 Ludibrium Maze PQ
Implemented Ludibrium Maze PQ.
2017-05-15 15:52:24 -03:00

445 lines
14 KiB
Java

/*
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.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.script.Invocable;
import javax.script.ScriptException;
import net.server.channel.Channel;
import net.server.world.MapleParty;
import net.server.world.MaplePartyCharacter;
import server.TimerManager;
import server.expeditions.MapleExpedition;
import server.maps.MapleMap;
import server.life.MapleMonster;
import server.life.MapleLifeFactory;
import client.MapleCharacter;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Array;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*
* @author Matze
*/
public class EventManager {
private Invocable iv;
private Channel cserv;
private Map<String, EventInstanceManager> instances = new HashMap<String, EventInstanceManager>();
private Map<String, Integer> instanceLocks = new HashMap<String, Integer>();
private List<Boolean> openedLobbys;
private Properties props = new Properties();
private String name;
private ScheduledFuture<?> schedule = null;
private Lock l = new ReentrantLock();
private static final int maxLobbys = 8; // an event manager holds up to this amount of concurrent lobbys
private static final long lobbyDelay = 10; // 10 seconds cooldown before reopening a lobby
public EventManager(Channel cserv, Invocable iv, String name) {
this.iv = iv;
this.cserv = cserv;
this.name = name;
this.openedLobbys = new ArrayList<>();
for(int i = 0; i < maxLobbys; i++) this.openedLobbys.add(false);
}
public void cancel() {
try {
iv.invokeFunction("cancelSchedule", (Object) null);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
}
private List<Integer> convertToIntegerArray(List<Double> list) {
List<Integer> intList = new ArrayList<>();
for(Double d: list) intList.add(d.intValue());
return intList;
}
private List<Integer> getLobbyRange() {
try {
return convertToIntegerArray((List<Double>)iv.invokeFunction("setLobbyRange", (Object) null));
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
return new ArrayList<>();
}
public void schedule(String methodName, long delay) {
schedule(methodName, null, delay);
}
public void schedule(final String methodName, final EventInstanceManager eim, long delay) {
schedule = TimerManager.getInstance().schedule(new Runnable() {
public void run() {
try {
iv.invokeFunction(methodName, eim);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
}, delay);
}
public void cancelSchedule() {
if(schedule != null)
schedule.cancel(false);
}
public ScheduledFuture<?> scheduleAtTimestamp(final String methodName, long timestamp) {
return TimerManager.getInstance().scheduleAtTimestamp(new Runnable() {
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 Channel getChannelServer() {
return cserv;
}
public EventInstanceManager getInstance(String name) {
return instances.get(name);
}
public Collection<EventInstanceManager> getInstances() {
return Collections.unmodifiableCollection(instances.values());
}
public EventInstanceManager newInstance(String name) {
EventInstanceManager ret = new EventInstanceManager(this, name);
instances.put(name, ret);
return ret;
}
public void disposeInstance(final String name) {
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
freeLobbyInstance(name);
instances.remove(name);
}
}, lobbyDelay * 1000);
}
public Invocable getIv() {
return iv;
}
public void setProperty(String key, String value) {
props.setProperty(key, value);
}
public String getProperty(String key) {
return props.getProperty(key);
}
public void setProperty(String key, int value) {
props.setProperty(key, value + "");
}
public int getIntProperty(String key) {
return Integer.parseInt(props.getProperty(key));
}
private boolean getLockLobby(int lobbyId) {
l.lock();
try {
return openedLobbys.get(lobbyId);
} finally {
l.unlock();
}
}
private void setLockLobby(int lobbyId, boolean lock) {
l.lock();
try {
openedLobbys.set(lobbyId, lock);
} finally {
l.unlock();
}
}
private boolean startLobbyInstance(int lobbyId) {
l.lock();
try {
if(!openedLobbys.get(lobbyId)) {
openedLobbys.set(lobbyId, true);
return true;
}
} finally {
l.unlock();
}
return false;
}
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;
}
public 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;
}
public boolean startInstance(MapleExpedition exped) {
return startInstance(-1, exped);
}
//Expedition method: starts an expedition
public boolean startInstance(int lobbyId, MapleExpedition exped) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
if(lobbyId == -1) return false;
}
else {
if(getLockLobby(lobbyId)) return false;
startLobbyInstance(lobbyId);
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
if(eim == null) {
if(lobbyId > -1) setLockLobby(lobbyId, false);
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.registerExpedition(exped);
exped.start();
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
//Regular method: player
public boolean startInstance(MapleCharacter chr) {
return startInstance(-1, chr);
}
public boolean startInstance(int lobbyId, MapleCharacter chr) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
if(lobbyId == -1) return false;
}
else {
if(getLockLobby(lobbyId)) return false;
startLobbyInstance(lobbyId);
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
if(eim == null) {
if(lobbyId > -1) setLockLobby(lobbyId, false);
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.registerPlayer(chr);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
//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) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
if(lobbyId == -1) return false;
}
else {
if(getLockLobby(lobbyId)) return false;
startLobbyInstance(lobbyId);
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
if(eim == null) {
if(lobbyId > -1) setLockLobby(lobbyId, false);
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.registerParty(party, map);
party.setEligibleMembers(null);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
//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) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
if(lobbyId == -1) return false;
}
else {
if(getLockLobby(lobbyId)) return false;
startLobbyInstance(lobbyId);
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : party.getLeaderId()));
if(eim == null) {
if(lobbyId > -1) setLockLobby(lobbyId, false);
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.registerParty(party, map);
party.setEligibleMembers(null);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
//non-PQ method for starting instance
public boolean startInstance(EventInstanceManager eim, String leader) {
return startInstance(-1, eim, leader);
}
public boolean startInstance(int lobbyId, EventInstanceManager eim, String leader) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
if(lobbyId == -1) return false;
}
else {
if(getLockLobby(lobbyId)) return false;
startLobbyInstance(lobbyId);
}
if(eim == null) {
if(lobbyId > -1) setLockLobby(lobbyId, false);
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
iv.invokeFunction("setup", eim);
eim.setProperty("leader", leader);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
public List<MaplePartyCharacter> getEligibleParty(MapleParty party) {
if (party == null) {
return(new ArrayList<>());
}
try {
Object p = iv.invokeFunction("getEligibleParty", party.getPartyMembers());
if(p != null) {
List<MaplePartyCharacter> 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));
}
}