White scroll & PiratePQ fix + Party for starters + concurrency protection on event scripts

Fixed successful scrolled items not using up an upgrade slot when using white scroll. Fixed some issues with the PiratePQ and added a "clear all boxes to complete a stage"-mode. Added "Party for Starters" feature. Added concurrency protection on event script modules.
This commit is contained in:
ronancpl
2017-10-13 03:31:51 -03:00
parent 6e1442af30
commit 1ec7487bd3
96 changed files with 470 additions and 109 deletions

View File

@@ -54,7 +54,7 @@ Overwrite whenever prompted with the JAR files under "jce_policy-7/UnlimitedJCEP
Now that the tools have been installed, test if they are working. Now that the tools have been installed, test if they are working.
For WampServer: For WampServer:
Once your done installing it, run it and you will see the Wamp icon on the bottom right corner. Once you're done installing it, run it and you will see the Wamp icon on the bottom right corner.
Left click it and click 'Put Online'. Left click it and click 'Put Online'.
In case of ORANGE ICON, change port 80 at "httpd.conf" to another, as it clashes with a Windows default port. In case of ORANGE ICON, change port 80 at "httpd.conf" to another, as it clashes with a Windows default port.
Then Left click it again and click 'Start All Services'. Then Left click it again and click 'Start All Services'.
@@ -73,11 +73,12 @@ Setting up the SQL: open MySQL Query Browser, and define these parameters at sta
Server Host: localhost Port: 3306 Username: root Server Host: localhost Port: 3306 Username: root
Now it must be done CAREFULLY: Now it must be done CAREFULLY:
1. File -> Open Script... -> Browse for "C:\MapleSolaxia\sql" -> db_database.sql, and execute it. 1. File -> Open Script... -> Browse for "C:\Nexon\MapleSolaxia\sql" -> db_database.sql, and execute it.
2. File -> Open Script... -> Browse for "C:\MapleSolaxia\sql" -> db_drops.sql, and execute it. 2. File -> Open Script... -> Browse for "C:\Nexon\MapleSolaxia\sql" -> db_drops.sql, and execute it.
Now it is OPTIONAL, you don't need to run it if you don't want, as it will simply change some NPC shops to set some new goods, not present in the original MapleStory, to sell: Now it is OPTIONAL, you don't need to run it if you don't want, as it will simply change some NPC shops to set some new goods, not present in the original MapleStory, to sell:
3. File -> Open Script... -> Browse for "C:\MapleSolaxia\sql" -> db_shopupdate.sql, and execute it.
3. File -> Open Script... -> Browse for "C:\Nexon\MapleSolaxia\sql" -> db_shopupdate.sql, and execute it.
At the end of the execution of these SQLs, you should have installed a database schema named "maplesolaxia". REGISTER YOUR FIRST ACCOUNT to be used in-game by creating manually a entry on the table "accounts" at that database with a login and a password. At the end of the execution of these SQLs, you should have installed a database schema named "maplesolaxia". REGISTER YOUR FIRST ACCOUNT to be used in-game by creating manually a entry on the table "accounts" at that database with a login and a password.

View File

@@ -1,4 +1,4 @@
#Thu, 05 Oct 2017 16:16:32 -0300 #Fri, 13 Oct 2017 03:24:23 -0300
C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2= C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2=

BIN
dist/MapleSolaxia.jar vendored

Binary file not shown.

View File

@@ -36,6 +36,7 @@ Quests:
Player Social Network: Player Social Network:
* Guild and Alliance system fully functional. * Guild and Alliance system fully functional.
* Beginners can create and join a "beginner-only" party (characters up to level 10).
Cash & Items: Cash & Items:
* EXP/DROP/Cosmetic Coupons 100%. * EXP/DROP/Cosmetic Coupons 100%.

View File

@@ -569,3 +569,15 @@ Refatorado sistema de schedules para disease expiretimes.
05 Outubro 2017, 05 Outubro 2017,
Alterado level mínimo para receber exp de um mob de base level - 5 para - 20 (cliente destaca infos do mob em vermelho se o jogador está abaixo desta faixa). Alterado level mínimo para receber exp de um mob de base level - 5 para - 20 (cliente destaca infos do mob em vermelho se o jogador está abaixo desta faixa).
07 Outubro 2017,
Consertado players podendo criar party sendo level menor que 10.
Players abaixo do level 10 agora podem convidar outros menores que 10 para party, se o servidor permitir.
09 Outubro 2017,
Adicionado proteção de acesso concorrente em invocação de scripts na EventInstanceManager.
Alterado tempo-limite em mapas da PiratePQ para seguir o determinado para cada mapa.
12 Outubro 2017,
Corrigido alguns bugs com a PPQ.
Se houve sucesso usando white scroll, slot ainda é usado.

View File

@@ -3,9 +3,19 @@
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="1"/> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="1"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2"> <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group> <group>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/npc/NPCConversationManager.java</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/portal/davy_next0.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/constants/ServerConstants.java</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/command/Commands.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/life/MapleMonster.java</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/portal/davy_next3.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/portal/davy_next1.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/portal/davy_next4.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleReactorStats.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleDoor.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/2094002.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/CathedralWedding.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/portal/davy_next2.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleMap.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/PiratePQ.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/reactor/2512000.js</file>
</group> </group>
</open-files> </open-files>
</project-private> </project-private>

View File

@@ -4,6 +4,8 @@
*/ */
var isPq = true; var isPq = true;
var isGrindMode = true; // stages done after breaking all boxes on maps
var minPlayers = 3, maxPlayers = 6; var minPlayers = 3, maxPlayers = 6;
var minLevel = 55, maxLevel = 100; var minLevel = 55, maxLevel = 100;
var entryMap = 925100000; var entryMap = 925100000;
@@ -14,7 +16,7 @@ var clearMap = 925100600;
var minMapId = 925100000; var minMapId = 925100000;
var maxMapId = 925100500; var maxMapId = 925100500;
var eventTime = 20; // 20 minutes var eventTime = 4; // 4 minutes
var lobbyRange = [0, 0]; var lobbyRange = [0, 0];
@@ -83,7 +85,11 @@ function setup(level, lobbyid) {
eim.setProperty("stage4", "0"); eim.setProperty("stage4", "0");
eim.setProperty("stage5", "0"); eim.setProperty("stage5", "0");
eim.setProperty("curStage", "1");
eim.setProperty("grindMode", isGrindMode ? "1" : "0");
eim.setProperty("openedChests", "0"); eim.setProperty("openedChests", "0");
eim.setProperty("openedBoxes", "0");
eim.getInstanceMap(925100000).resetPQ(level); eim.getInstanceMap(925100000).resetPQ(level);
eim.getInstanceMap(925100000).shuffleReactors(); eim.getInstanceMap(925100000).shuffleReactors();
@@ -190,6 +196,37 @@ function playerExit(eim, player) {
player.changeMap(exitMap, 0); player.changeMap(exitMap, 0);
} }
function changedMapInside(eim, mapid) {
var stage = eim.getIntProperty("curStage");
if(stage == 1) {
if(mapid == 925100100) {
eim.restartEventTimer(6 * 60 * 1000);
eim.setIntProperty("curStage", 2);
}
} else if(stage == 2) {
if(mapid == 925100200) {
eim.restartEventTimer(6 * 60 * 1000);
eim.setIntProperty("curStage", 3);
}
} else if(stage == 3) {
if(mapid == 925100300) {
eim.restartEventTimer(6 * 60 * 1000);
eim.setIntProperty("curStage", 4);
}
} else if(stage == 4) {
if(mapid == 925100400) {
eim.restartEventTimer(6 * 60 * 1000);
eim.setIntProperty("curStage", 5);
}
} else if(stage == 5) {
if(mapid == 925100500) {
eim.restartEventTimer(8 * 60 * 1000);
eim.setIntProperty("curStage", 6);
}
}
}
function changedMap(eim, player, mapid) { function changedMap(eim, player, mapid) {
if (mapid < minMapId || mapid > maxMapId) { if (mapid < minMapId || mapid > maxMapId) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) { if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
@@ -198,6 +235,8 @@ function changedMap(eim, player, mapid) {
} }
else else
eim.unregisterPlayer(player); eim.unregisterPlayer(player);
} else {
changedMapInside(eim, mapid);
} }
} }
@@ -254,6 +293,10 @@ function clearPQ(eim) {
eim.stopEventTimer(); eim.stopEventTimer();
eim.setEventCleared(); eim.setEventCleared();
var chests = parseInt(eim.getProperty("openedChests"));
var expGain = (chests == 0 ? 28000 : (chests == 1 ? 35000 : 42000));
eim.giveEventPlayersExp(expGain);
eim.warpEventTeam(925100600); eim.warpEventTeam(925100600);
} }
@@ -262,11 +305,30 @@ function isLordPirate(mob) {
return (mobid == 9300105) || (mobid == 9300106) || (mobid == 9300107) || (mobid == 9300119); return (mobid == 9300105) || (mobid == 9300106) || (mobid == 9300107) || (mobid == 9300119);
} }
function passedGrindMode(map, eim) {
if(eim.getIntProperty("grindMode") == 0) return true;
return eim.activatedAllReactorsOnMap(map, 2511000, 2517999);
}
function monsterKilled(mob, eim) { function monsterKilled(mob, eim) {
var map = mob.getMap();
if(isLordPirate(mob)) { // lord pirate defeated, spawn the little fella! if(isLordPirate(mob)) { // lord pirate defeated, spawn the little fella!
mob.getMap().broadcastStringMessage(5, "As Lord Pirate dies, Wu Yang is released!"); map.broadcastStringMessage(5, "As Lord Pirate dies, Wu Yang is released!");
eim.spawnNpc(2094001, new java.awt.Point(777, 140), mob.getMap()); eim.spawnNpc(2094001, new java.awt.Point(777, 140), mob.getMap());
} }
if(map.countMonsters() == 0) {
var stage = ((map.getId() % 1000) / 100) + 1;
if((stage == 1 || stage == 3 || stage == 4) && passedGrindMode(map, eim)) {
eim.showClearEffect(map.getId());
} else if(stage == 5) {
if(map.getReactorByName("sMob1").getState() >= 1 && map.getReactorByName("sMob2").getState() >= 1 && map.getReactorByName("sMob3").getState() >= 1 && map.getReactorByName("sMob4").getState() >= 1) {
eim.showClearEffect(map.getId());
}
}
}
} }
function allMonstersDead(eim) {} function allMonstersDead(eim) {}

View File

@@ -73,6 +73,7 @@ function action(mode, type, selection) {
cm.gainItem(4001122,-20); cm.gainItem(4001122,-20);
cm.getMap().killAllMonsters(); cm.getMap().killAllMonsters();
eim.setProperty("stage2", "3"); eim.setProperty("stage2", "3");
eim.showClearEffect(cm.getMapId());
} else { } else {
cm.sendNext("We are heading into the Pirate Ship now! To get in, we must qualify ourselves as noble pirates. Hunt me 20 Veteran Medals."); cm.sendNext("We are heading into the Pirate Ship now! To get in, we must qualify ourselves as noble pirates. Hunt me 20 Veteran Medals.");
if(cm.countMonster() < 1) cm.getPlayer().getMap().spawnAllMonsterIdFromMapSpawnList(9300116, level, true); if(cm.countMonster() < 1) cm.getPlayer().getMap().spawnAllMonsterIdFromMapSpawnList(9300116, level, true);
@@ -113,7 +114,7 @@ function action(mode, type, selection) {
break; break;
case 925100202: case 925100202:
case 925100302: case 925100302:
cm.sendNext("These are the Captains and Krus which devote their whole life to Lord Pirate. Kill them as you see fit."); cm.sendNext("These are the Captains and Krus that devote their lives to the Lord Pirate. Kill them as you see fit.");
cm.dispose(); cm.dispose();
break; break;
case 925100400: case 925100400:

View File

@@ -1,5 +1,10 @@
function passedGrindMode(map, eim) {
if(eim.getIntProperty("grindMode") == 0) return true;
return eim.activatedAllReactorsOnMap(map, 2511000, 2517999);
}
function enter(pi) { function enter(pi) {
if (pi.getMap().getMonsters().size() == 0) { if (pi.getMap().getMonsters().size() == 0 && passedGrindMode(pi.getMap(), pi.getEventInstance())) {
pi.warp(925100100,0); //next pi.warp(925100100,0); //next
return(true); return(true);
} else { } else {

View File

@@ -1,5 +1,10 @@
function passedGrindMode(map, eim) {
if(eim.getIntProperty("grindMode") == 0) return true;
return eim.activatedAllReactorsOnMap(map, 2511000, 2517999);
}
function enter(pi) { function enter(pi) {
if (pi.getMap().getMonsters().size() == 0) { if (pi.getMap().getMonsters().size() == 0 && passedGrindMode(pi.getMap(), pi.getEventInstance())) {
pi.warp(925100300,0); //next pi.warp(925100300,0); //next
return(true); return(true);
} else { } else {

View File

@@ -1,5 +1,10 @@
function passedGrindMode(map, eim) {
if(eim.getIntProperty("grindMode") == 0) return true;
return eim.activatedAllReactorsOnMap(map, 2511000, 2517999);
}
function enter(pi) { function enter(pi) {
if (pi.getMap().getMonsters().size() == 0) { if (pi.getMap().getMonsters().size() == 0 && passedGrindMode(pi.getMap(), pi.getEventInstance())) {
pi.warp(925100400,0); //next pi.warp(925100400,0); //next
return(true); return(true);
} else { } else {

View File

@@ -26,10 +26,10 @@
function act() { function act() {
var eim = rm.getPlayer().getEventInstance(); var eim = rm.getPlayer().getEventInstance();
var now = eim.getProperty("openedBoxes"); var now = eim.getIntProperty("openedBoxes");
var nextNum = now + 1; var nextNum = now + 1;
eim.setProperty("openedBoxes", nextNum); eim.setIntProperty("openedBoxes", nextNum);
rm.spawnMonster(9300109, 3); rm.spawnMonster(9300109, 3);
rm.spawnMonster(9300110, 5); rm.spawnMonster(9300110, 5);
rm.mapMessage(5, "Some monsters are summoned.");
} }

View File

@@ -24,10 +24,21 @@
*Pirate PQ Reactor *Pirate PQ Reactor
*/ */
function passedGrindMode(map, eim) {
if(eim.getIntProperty("grindMode") == 0) return true;
return eim.activatedAllReactorsOnMap(map, 2511000, 2517999);
}
function act() { function act() {
var eim = rm.getPlayer().getEventInstance(); var eim = rm.getPlayer().getEventInstance();
var now = parseInt(eim.getProperty("openedBoxes")); var now = eim.getIntProperty("openedBoxes");
var nextNum = now + 1; var nextNum = now + 1;
eim.setProperty("openedBoxes", nextNum); eim.setIntProperty("openedBoxes", nextNum);
rm.dropItems(true, 1, 30, 60, 15); rm.dropItems(true, 1, 30, 60, 15);
var map = rm.getMap();
if (map.getMonsters().size() == 0 && passedGrindMode(map, eim)) {
eim.showClearEffect(map.getId());
}
} }

View File

@@ -26,8 +26,8 @@
function act() { function act() {
var eim = rm.getPlayer().getEventInstance(); var eim = rm.getPlayer().getEventInstance();
var now = parseInt(eim.getProperty("openedChests")); var now = eim.getIntProperty("openedChests");
var nextNum = now + 1; var nextNum = now + 1;
eim.setProperty("openedChests", nextNum.toString()); eim.setIntProperty("openedChests", nextNum);
rm.dropItems(true, 1, 50, 100, 15); rm.dropItems(true, 1, 50, 100, 15);
} }

View File

@@ -32,4 +32,9 @@ function act() {
var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight); var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight);
rm.getReactor().getMap().setAllowSpawnPointInBox(false, denyArea); rm.getReactor().getMap().setAllowSpawnPointInBox(false, denyArea);
var map = rm.getReactor().getMap();
if(map.getReactorByName("sMob2").getState() >= 1 && map.getReactorByName("sMob3").getState() >= 1 && map.getReactorByName("sMob4").getState() >= 1 && map.countMonsters() == 0) {
rm.getEventInstance().showClearEffect(map.getId());
}
} }

View File

@@ -32,4 +32,9 @@ function act() {
var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight); var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight);
rm.getReactor().getMap().setAllowSpawnPointInBox(false, denyArea); rm.getReactor().getMap().setAllowSpawnPointInBox(false, denyArea);
var map = rm.getReactor().getMap();
if(map.getReactorByName("sMob1").getState() >= 1 && map.getReactorByName("sMob3").getState() >= 1 && map.getReactorByName("sMob4").getState() >= 1 && map.countMonsters() == 0) {
rm.getEventInstance().showClearEffect(map.getId());
}
} }

View File

@@ -32,4 +32,9 @@ function act() {
var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight); var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight);
rm.getReactor().getMap().setAllowSpawnPointInBox(false, denyArea); rm.getReactor().getMap().setAllowSpawnPointInBox(false, denyArea);
var map = rm.getReactor().getMap();
if(map.getReactorByName("sMob1").getState() >= 1 && map.getReactorByName("sMob2").getState() >= 1 && map.getReactorByName("sMob4").getState() >= 1 && map.countMonsters() == 0) {
rm.getEventInstance().showClearEffect(map.getId());
}
} }

View File

@@ -31,5 +31,10 @@ function act() {
var denyPos = rm.getReactor().getPosition(); var denyPos = rm.getReactor().getPosition();
var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight); var denyArea = new Rectangle(denyPos.getX() - denyWidth / 2, denyPos.getY() - denyHeight / 2, denyWidth, denyHeight);
rm.getReactor().getMap().setAllowSpawnPointInBox(false, denyArea); var map = rm.getReactor().getMap();
map.setAllowSpawnPointInBox(false, denyArea);
if(map.getReactorByName("sMob1").getState() >= 1 && map.getReactorByName("sMob2").getState() >= 1 && map.getReactorByName("sMob3").getState() >= 1 && map.countMonsters() == 0) {
rm.getEventInstance().showClearEffect(map.getId());
}
} }

View File

@@ -147,6 +147,7 @@ import constants.skills.Spearman;
import constants.skills.SuperGM; import constants.skills.SuperGM;
import constants.skills.Swordsman; import constants.skills.Swordsman;
import constants.skills.ThunderBreaker; import constants.skills.ThunderBreaker;
import net.server.channel.handlers.PartyOperationHandler;
import scripting.item.ItemScriptManager; import scripting.item.ItemScriptManager;
import server.maps.MapleMapItem; import server.maps.MapleMapItem;
@@ -1902,7 +1903,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}, healInterval, healInterval); }, healInterval, healInterval);
} }
public void disableDoor() { public void disableDoorSpawn() {
canDoor = false; canDoor = false;
TimerManager.getInstance().schedule(new Runnable() { TimerManager.getInstance().schedule(new Runnable() {
@Override @Override
@@ -4803,6 +4804,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
recalcLocalStats(); recalcLocalStats();
setMPC(new MaplePartyCharacter(this)); setMPC(new MaplePartyCharacter(this));
silentPartyUpdate(); silentPartyUpdate();
if(level == 10 && party != null) {
if(this.isPartyLeader()) party.assignNewLeader(client);
PartyOperationHandler.leaveParty(party, mpc, client);
client.announceHint("You have reached #blevel 10#k, therefore you must leave your #rstarter party#k.");
}
if (this.guildid > 0) { if (this.guildid > 0) {
getGuild().broadcast(MaplePacketCreator.levelUpMessage(2, level, name), this.getId()); getGuild().broadcast(MaplePacketCreator.levelUpMessage(2, level, name), this.getId());
} }

View File

@@ -43,6 +43,7 @@ public class ServerConstants {
public static final boolean USE_ITEM_SORT = true; public static final boolean USE_ITEM_SORT = true;
public static final boolean USE_ITEM_SORT_BY_NAME = false; //Item sorting based on name rather than id. public static final boolean USE_ITEM_SORT_BY_NAME = false; //Item sorting based on name rather than id.
public static final boolean USE_PARTY_SEARCH = false; public static final boolean USE_PARTY_SEARCH = false;
public static final boolean USE_PARTY_FOR_STARTERS = true; //Players level 10 or below can create/invite other players on the given level range.
public static final boolean USE_AUTOBAN = false; //Commands the server to detect infractors automatically. public static final boolean USE_AUTOBAN = false; //Commands the server to detect infractors automatically.
public static final boolean USE_AUTOSAVE = true; //Enables server autosaving feature (saves characters to DB each 1 hour). public static final boolean USE_AUTOSAVE = true; //Enables server autosaving feature (saves characters to DB each 1 hour).
public static final boolean USE_SERVER_AUTOASSIGNER = true; //Server-builtin autoassigner, uses algorithm based on distributing AP accordingly with required secondary stat on equipments. public static final boolean USE_SERVER_AUTOASSIGNER = true; //Server-builtin autoassigner, uses algorithm based on distributing AP accordingly with required secondary stat on equipments.

View File

@@ -30,37 +30,16 @@ import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor; import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleCharacter; import client.MapleCharacter;
import client.MapleClient; import client.MapleClient;
import constants.ServerConstants;
import scripting.event.EventInstanceManager; import scripting.event.EventInstanceManager;
import server.maps.MapleMap; import server.maps.MapleMap;
public final class PartyOperationHandler extends AbstractMaplePacketHandler { public final class PartyOperationHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public static void leaveParty(MapleParty party, MaplePartyCharacter partyplayer, MapleClient c) {
int operation = slea.readByte();
MapleCharacter player = c.getPlayer();
World world = c.getWorldServer(); World world = c.getWorldServer();
MapleParty party = player.getParty(); MapleCharacter player = c.getPlayer();
MaplePartyCharacter partyplayer = player.getMPC();
switch (operation) {
case 1: { // create
if(player.getLevel() < 10) {
c.announce(MaplePacketCreator.partyStatusMessage(10));
return;
}
if (player.getParty() == null) {
partyplayer = new MaplePartyCharacter(player);
party = world.createParty(partyplayer);
player.setParty(party);
player.setMPC(partyplayer);
player.getMap().addPartyMember(player);
player.silentPartyUpdate();
c.announce(MaplePacketCreator.partyCreated(partyplayer));
} else {
c.announce(MaplePacketCreator.serverNotice(5, "You can't create a party as you are already in one."));
}
break;
}
case 2: {
if (party != null && partyplayer != null) { if (party != null && partyplayer != null) {
if (partyplayer.getId() == party.getLeaderId()) { if (partyplayer.getId() == party.getLeaderId()) {
c.getWorldServer().removeMapPartyMembers(party.getId()); c.getWorldServer().removeMapPartyMembers(party.getId());
@@ -80,9 +59,39 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
player.setParty(null); player.setParty(null);
} }
}
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int operation = slea.readByte();
MapleCharacter player = c.getPlayer();
World world = c.getWorldServer();
MapleParty party = player.getParty();
MaplePartyCharacter partyplayer = player.getMPC();
switch (operation) {
case 1: { // create
if(player.getLevel() < 10 && !ServerConstants.USE_PARTY_FOR_STARTERS) {
c.announce(MaplePacketCreator.partyStatusMessage(10));
return;
}
if (player.getParty() == null) {
partyplayer = new MaplePartyCharacter(player);
party = world.createParty(partyplayer);
player.setParty(party);
player.setMPC(partyplayer);
player.getMap().addPartyMember(player);
player.silentPartyUpdate();
c.announce(MaplePacketCreator.partyCreated(partyplayer));
} else {
c.announce(MaplePacketCreator.serverNotice(5, "You can't create a party as you are already in one."));
}
break; break;
} }
case 3: {//join case 2: { // leave/disband
leaveParty(party, partyplayer, c);
break;
}
case 3: { // join
int partyid = slea.readInt(); int partyid = slea.readInt();
if (c.getPlayer().getParty() == null) { if (c.getPlayer().getParty() == null) {
party = world.getParty(partyid); party = world.getParty(partyid);
@@ -105,16 +114,26 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
} }
break; break;
} }
case 4: {//invite case 4: { // invite
String name = slea.readMapleAsciiString(); String name = slea.readMapleAsciiString();
MapleCharacter invited = world.getPlayerStorage().getCharacterByName(name); MapleCharacter invited = world.getPlayerStorage().getCharacterByName(name);
if (invited != null) { if (invited != null) {
if(invited.getLevel() < 10) { //min requirement is level 10 if(invited.getLevel() < 10 && (!ServerConstants.USE_PARTY_FOR_STARTERS || player.getLevel() >= 10)) { //min requirement is level 10
c.announce(MaplePacketCreator.serverNotice(5, "The player you have invited does not meet the requirements.")); c.announce(MaplePacketCreator.serverNotice(5, "The player you have invited does not meet the requirements."));
return; return;
} }
if(ServerConstants.USE_PARTY_FOR_STARTERS && invited.getLevel() >= 10 && player.getLevel() < 10) { //trying to invite high level
c.announce(MaplePacketCreator.serverNotice(5, "The player you have invited does not meet the requirements."));
return;
}
if (invited.getParty() == null) { if (invited.getParty() == null) {
if (player.getParty() == null) { if (player.getParty() == null) {
if(player.getLevel() < 10 && !ServerConstants.USE_PARTY_FOR_STARTERS) {
c.announce(MaplePacketCreator.partyStatusMessage(10));
return;
}
partyplayer = new MaplePartyCharacter(player); partyplayer = new MaplePartyCharacter(player);
party = world.createParty(partyplayer); party = world.createParty(partyplayer);
player.setParty(party); player.setParty(party);
@@ -158,7 +177,7 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
} }
break; break;
} }
case 6: { case 6: { // change leader
int newLeader = slea.readInt(); int newLeader = slea.readInt();
MaplePartyCharacter newLeadr = party.getMemberById(newLeader); MaplePartyCharacter newLeadr = party.getMemberById(newLeader);
world.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, newLeadr); world.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, newLeadr);

View File

@@ -21,6 +21,7 @@
*/ */
package net.server.world; package net.server.world;
import client.MapleClient;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
@@ -195,6 +196,24 @@ public class MapleParty {
return slot; return slot;
} }
public void assignNewLeader(MapleClient c) {
World world = c.getWorldServer();
MaplePartyCharacter newLeadr = null;
lock.lock();
try {
for(MaplePartyCharacter mpc : members) {
if(mpc.getId() != leaderId && (newLeadr == null || newLeadr.getLevel() < mpc.getLevel())) {
newLeadr = mpc;
}
}
} finally {
lock.unlock();
}
if(newLeadr != null) world.updateParty(this.getId(), PartyOperation.CHANGE_LEADER, newLeadr);
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;

View File

@@ -27,7 +27,6 @@ import java.util.LinkedHashMap;
import java.util.Collection; import java.util.Collection;
import server.maps.MapleDoor; import server.maps.MapleDoor;
import server.MapleStatEffect;
import client.MapleCharacter; import client.MapleCharacter;
import client.MapleJob; import client.MapleJob;
import java.util.Collections; import java.util.Collections;

View File

@@ -34,6 +34,8 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.Iterator; import java.util.Iterator;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -50,6 +52,7 @@ import server.expeditions.MapleExpedition;
import server.life.MapleMonster; import server.life.MapleMonster;
import server.maps.MapleMap; import server.maps.MapleMap;
import server.maps.MapleMapFactory; import server.maps.MapleMapFactory;
import server.maps.MapleReactor;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import client.MapleCharacter; import client.MapleCharacter;
import client.SkillFactory; import client.SkillFactory;
@@ -87,6 +90,8 @@ public class EventInstanceManager {
private List<Integer> mapIds = new LinkedList<Integer>(); private List<Integer> mapIds = new LinkedList<Integer>();
private List<Boolean> isInstanced = new LinkedList<Boolean>(); private List<Boolean> isInstanced = new LinkedList<Boolean>();
private final ReentrantReadWriteLock mutex = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock mutex = new ReentrantReadWriteLock();
private final Lock pL = new ReentrantLock();
private final Lock sL = new ReentrantLock();
private final ReadLock rL = mutex.readLock(); private final ReadLock rL = mutex.readLock();
private final WriteLock wL = mutex.writeLock(); private final WriteLock wL = mutex.writeLock();
private ScheduledFuture<?> event_schedule = null; private ScheduledFuture<?> event_schedule = null;
@@ -225,7 +230,13 @@ public class EventInstanceManager {
} }
chr.setEventInstance(this); chr.setEventInstance(this);
sL.lock();
try {
em.getIv().invokeFunction("playerEntry", this, chr); em.getIv().invokeFunction("playerEntry", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -237,7 +248,13 @@ public class EventInstanceManager {
} }
try { try {
unregisterPlayer(chr); unregisterPlayer(chr);
sL.lock();
try {
em.getIv().invokeFunction("playerExit", this, chr); em.getIv().invokeFunction("playerExit", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -268,7 +285,13 @@ public class EventInstanceManager {
public void run() { public void run() {
try { try {
dismissEventTimer(); dismissEventTimer();
sL.lock();
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this); em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
@@ -286,7 +309,13 @@ public class EventInstanceManager {
public void run() { public void run() {
try { try {
dismissEventTimer(); dismissEventTimer();
sL.lock();
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this); em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
@@ -353,8 +382,13 @@ public class EventInstanceManager {
} }
public void unregisterPlayer(MapleCharacter chr) { public void unregisterPlayer(MapleCharacter chr) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("playerUnregistered", EventInstanceManager.this, chr); em.getIv().invokeFunction("playerUnregistered", EventInstanceManager.this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
} }
@@ -408,28 +442,48 @@ public class EventInstanceManager {
} }
public void movePlayer(MapleCharacter chr) { public void movePlayer(MapleCharacter chr) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("moveMap", this, chr); em.getIv().invokeFunction("moveMap", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
public void changedMap(MapleCharacter chr, int mapId) { // optional public void changedMap(MapleCharacter chr, int mapId) { // optional
try {
sL.lock();
try { try {
em.getIv().invokeFunction("changedMap", this, chr, mapId); em.getIv().invokeFunction("changedMap", this, chr, mapId);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {} } catch (ScriptException | NoSuchMethodException ex) {}
} }
public void afterChangedMap(MapleCharacter chr, int mapId) { // optional public void afterChangedMap(MapleCharacter chr, int mapId) { // optional
try {
sL.lock();
try { try {
em.getIv().invokeFunction("afterChangedMap", this, chr, mapId); em.getIv().invokeFunction("afterChangedMap", this, chr, mapId);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {} } catch (ScriptException | NoSuchMethodException ex) {}
} }
public void changedLeader(MapleCharacter ldr) { public void changedLeader(MapleCharacter ldr) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("changedLeader", this, ldr); em.getIv().invokeFunction("changedLeader", this, ldr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -439,14 +493,24 @@ public class EventInstanceManager {
public void monsterKilled(MapleMonster mob) { public void monsterKilled(MapleMonster mob) {
mobs.remove(mob); mobs.remove(mob);
try {
sL.lock();
try { try {
em.getIv().invokeFunction("monsterKilled", mob, this); em.getIv().invokeFunction("monsterKilled", mob, this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
if (mobs.isEmpty()) { if (mobs.isEmpty()) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("allMonstersDead", this); em.getIv().invokeFunction("allMonstersDead", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -454,16 +518,26 @@ public class EventInstanceManager {
} }
public void friendlyKilled(MapleMonster mob) { public void friendlyKilled(MapleMonster mob) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("friendlyKilled", mob, this); em.getIv().invokeFunction("friendlyKilled", mob, this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
//optional //optional
} }
} }
public void playerKilled(MapleCharacter chr) { public void playerKilled(MapleCharacter chr) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("playerDead", this, chr); em.getIv().invokeFunction("playerDead", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -471,7 +545,15 @@ public class EventInstanceManager {
public boolean revivePlayer(MapleCharacter chr) { public boolean revivePlayer(MapleCharacter chr) {
try { try {
Object b = em.getIv().invokeFunction("playerRevive", this, chr); Object b;
sL.lock();
try {
b = em.getIv().invokeFunction("playerRevive", this, chr);
} finally {
sL.unlock();
}
if (b instanceof Boolean) { if (b instanceof Boolean) {
return (Boolean) b; return (Boolean) b;
} }
@@ -482,8 +564,13 @@ public class EventInstanceManager {
} }
public void playerDisconnected(MapleCharacter chr) { public void playerDisconnected(MapleCharacter chr) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("playerDisconnected", this, chr); em.getIv().invokeFunction("playerDisconnected", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -497,7 +584,15 @@ public class EventInstanceManager {
public void monsterKilled(MapleCharacter chr, MapleMonster mob) { public void monsterKilled(MapleCharacter chr, MapleMonster mob) {
try { try {
Integer kc = killCount.get(chr); Integer kc = killCount.get(chr);
int inc = ((Double) em.getIv().invokeFunction("monsterValue", this, mob.getId())).intValue(); int inc;
sL.lock();
try {
inc = ((Double) em.getIv().invokeFunction("monsterValue", this, mob.getId())).intValue();
} finally {
sL.unlock();
}
if (kc == null) { if (kc == null) {
kc = inc; kc = inc;
} else { } else {
@@ -525,8 +620,13 @@ public class EventInstanceManager {
} }
public void dispose() { public void dispose() {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("dispose", this); em.getIv().invokeFunction("dispose", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -562,8 +662,13 @@ public class EventInstanceManager {
public void run() { public void run() {
if(em == null) return; if(em == null) return;
try {
sL.lock();
try { try {
em.getIv().invokeFunction(methodName, EventInstanceManager.this); em.getIv().invokeFunction(methodName, EventInstanceManager.this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -613,52 +718,88 @@ public class EventInstanceManager {
} }
public void setProperty(String key, String value) { public void setProperty(String key, String value) {
pL.lock();
try {
props.setProperty(key, value); props.setProperty(key, value);
} finally {
pL.unlock();
}
} }
public Object setProperty(String key, String value, boolean prev) { public Object setProperty(String key, String value, boolean prev) {
pL.lock();
try {
return props.setProperty(key, value); return props.setProperty(key, value);
} finally {
pL.unlock();
}
} }
public String getProperty(String key) { public String getProperty(String key) {
pL.lock();
try {
return props.getProperty(key); return props.getProperty(key);
} finally {
pL.unlock();
} }
public Properties getProperties() {
return props;
} }
public int getIntProperty(String key) { public int getIntProperty(String key) {
pL.lock();
try {
return Integer.parseInt(props.getProperty(key)); return Integer.parseInt(props.getProperty(key));
} finally {
pL.unlock();
}
} }
public void leftParty(MapleCharacter chr) { public void leftParty(MapleCharacter chr) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("leftParty", this, chr); em.getIv().invokeFunction("leftParty", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
public void disbandParty() { public void disbandParty() {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("disbandParty", this); em.getIv().invokeFunction("disbandParty", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
public void clearPQ() { public void clearPQ() {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("clearPQ", this); em.getIv().invokeFunction("clearPQ", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
public void removePlayer(MapleCharacter chr) { public void removePlayer(MapleCharacter chr) {
try {
sL.lock();
try { try {
em.getIv().invokeFunction("playerExit", this, chr); em.getIv().invokeFunction("playerExit", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) { } catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@@ -1140,4 +1281,20 @@ public class EventInstanceManager {
wL.unlock(); wL.unlock();
} }
} }
public boolean activatedAllReactorsOnMap(int mapId, int minReactorId, int maxReactorId) {
return activatedAllReactorsOnMap(this.getMapInstance(mapId), minReactorId, maxReactorId);
}
public boolean activatedAllReactorsOnMap(MapleMap map, int minReactorId, int maxReactorId) {
if(map == null) return true;
for(MapleReactor mr : map.getReactorsByIdRange(minReactorId, maxReactorId)) {
if(mr.getReactorType() != -1) {
return false;
}
}
return true;
}
} }

View File

@@ -879,7 +879,7 @@ public class MapleItemInformationProvider {
break; break;
} }
if (!ItemConstants.isCleanSlate(scrollId)) { if (!ItemConstants.isCleanSlate(scrollId)) {
if (!assertGM && !usingWhiteScroll) { if (!assertGM) {
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1)); nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
} }
nEquip.setLevel((byte) (nEquip.getLevel() + 1)); nEquip.setLevel((byte) (nEquip.getLevel() + 1));

View File

@@ -23,13 +23,11 @@ package server;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import net.server.world.MaplePartyCharacter; import net.server.world.MaplePartyCharacter;
import provider.MapleData; import provider.MapleData;
@@ -896,7 +894,7 @@ public class MapleStatEffect {
door.getTarget().spawnDoor(door.getAreaDoor()); door.getTarget().spawnDoor(door.getAreaDoor());
door.getTown().spawnDoor(door.getTownDoor()); door.getTown().spawnDoor(door.getTownDoor());
applyto.disableDoor(); applyto.disableDoorSpawn();
} else { } else {
MapleInventoryManipulator.addFromDrop(applyto.getClient(), new Item(4006000, (short) 0, (short) 1), false); MapleInventoryManipulator.addFromDrop(applyto.getClient(), new Item(4006000, (short) 0, (short) 1), false);

View File

@@ -22,6 +22,7 @@
package server.maps; package server.maps;
import java.awt.Point; import java.awt.Point;
import java.util.List;
import tools.Pair; import tools.Pair;
import server.MaplePortal; import server.MaplePortal;
@@ -74,11 +75,13 @@ public class MapleDoor {
} }
private MaplePortal getDoorPortal(int slot) { private MaplePortal getDoorPortal(int slot) {
List<MaplePortal> avail = town.getAvailableDoorPortals();
try { try {
return town.getAvailableDoorPortals().get(slot); return avail.get(slot);
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
try { try {
return town.getAvailableDoorPortals().get(0); return avail.get(0);
} catch (IndexOutOfBoundsException ex) { } catch (IndexOutOfBoundsException ex) {
return null; return null;
} }

View File

@@ -1339,6 +1339,27 @@ public class MapleMap {
} }
} }
public List<MapleReactor> getReactorsByIdRange(final int first, final int last) {
List<MapleReactor> list = new LinkedList<>();
objectRLock.lock();
try {
for (MapleMapObject obj : mapobjects.values()) {
if (obj.getType() == MapleMapObjectType.REACTOR) {
MapleReactor mr = (MapleReactor) obj;
if (mr.getId() >= first && mr.getId() <= last) {
list.add(mr);
}
}
}
return list;
} finally {
objectRLock.unlock();
}
}
public MapleReactor getReactorByName(String name) { public MapleReactor getReactorByName(String name) {
objectRLock.lock(); objectRLock.lock();
try { try {
@@ -1607,7 +1628,7 @@ public class MapleMap {
try { try {
List<MaplePortal> availablePortals = new ArrayList<>(); List<MaplePortal> availablePortals = new ArrayList<>();
for (MaplePortal port : getPortals()) { for (MaplePortal port : portals.values()) {
if (port.getType() == MaplePortal.DOOR_PORTAL) { if (port.getType() == MaplePortal.DOOR_PORTAL) {
availablePortals.add(port); availablePortals.add(port);
} }
@@ -2117,9 +2138,11 @@ public class MapleMap {
return null; return null;
} }
/*
public Collection<MaplePortal> getPortals() { public Collection<MaplePortal> getPortals() {
return Collections.unmodifiableCollection(portals.values()); return Collections.unmodifiableCollection(portals.values());
} }
*/
public void removePlayer(MapleCharacter chr) { public void removePlayer(MapleCharacter chr) {
chrWLock.lock(); chrWLock.lock();