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.
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'.
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'.
@@ -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
Now it must be done CAREFULLY:
1. File -> Open Script... -> Browse for "C:\MapleSolaxia\sql" -> db_database.sql, and execute it.
2. File -> Open Script... -> Browse for "C:\MapleSolaxia\sql" -> db_drops.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:\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:
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.

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=

BIN
dist/MapleSolaxia.jar vendored

Binary file not shown.

View File

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

View File

@@ -568,4 +568,16 @@ Corrigido bug com scrolls n
Refatorado sistema de schedules para disease expiretimes.
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"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/npc/NPCConversationManager.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/constants/ServerConstants.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/life/MapleMonster.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/portal/davy_next0.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/command/Commands.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>
</open-files>
</project-private>

View File

@@ -4,6 +4,8 @@
*/
var isPq = true;
var isGrindMode = true; // stages done after breaking all boxes on maps
var minPlayers = 3, maxPlayers = 6;
var minLevel = 55, maxLevel = 100;
var entryMap = 925100000;
@@ -14,7 +16,7 @@ var clearMap = 925100600;
var minMapId = 925100000;
var maxMapId = 925100500;
var eventTime = 20; // 20 minutes
var eventTime = 4; // 4 minutes
var lobbyRange = [0, 0];
@@ -83,7 +85,11 @@ function setup(level, lobbyid) {
eim.setProperty("stage4", "0");
eim.setProperty("stage5", "0");
eim.setProperty("curStage", "1");
eim.setProperty("grindMode", isGrindMode ? "1" : "0");
eim.setProperty("openedChests", "0");
eim.setProperty("openedBoxes", "0");
eim.getInstanceMap(925100000).resetPQ(level);
eim.getInstanceMap(925100000).shuffleReactors();
@@ -190,6 +196,37 @@ function playerExit(eim, player) {
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) {
if (mapid < minMapId || mapid > maxMapId) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
@@ -198,6 +235,8 @@ function changedMap(eim, player, mapid) {
}
else
eim.unregisterPlayer(player);
} else {
changedMapInside(eim, mapid);
}
}
@@ -254,6 +293,10 @@ function clearPQ(eim) {
eim.stopEventTimer();
eim.setEventCleared();
var chests = parseInt(eim.getProperty("openedChests"));
var expGain = (chests == 0 ? 28000 : (chests == 1 ? 35000 : 42000));
eim.giveEventPlayersExp(expGain);
eim.warpEventTeam(925100600);
}
@@ -262,11 +305,30 @@ function isLordPirate(mob) {
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) {
var map = mob.getMap();
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());
}
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) {}

View File

@@ -73,6 +73,7 @@ function action(mode, type, selection) {
cm.gainItem(4001122,-20);
cm.getMap().killAllMonsters();
eim.setProperty("stage2", "3");
eim.showClearEffect(cm.getMapId());
} 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.");
if(cm.countMonster() < 1) cm.getPlayer().getMap().spawnAllMonsterIdFromMapSpawnList(9300116, level, true);
@@ -113,7 +114,7 @@ function action(mode, type, selection) {
break;
case 925100202:
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();
break;
case 925100400:

View File

@@ -1,9 +1,14 @@
function passedGrindMode(map, eim) {
if(eim.getIntProperty("grindMode") == 0) return true;
return eim.activatedAllReactorsOnMap(map, 2511000, 2517999);
}
function enter(pi) {
if (pi.getMap().getMonsters().size() == 0) {
pi.warp(925100100,0); //next
return(true);
} else {
pi.playerMessage(5, "The portal is not opened yet.");
return(false);
}
if (pi.getMap().getMonsters().size() == 0 && passedGrindMode(pi.getMap(), pi.getEventInstance())) {
pi.warp(925100100,0); //next
return(true);
} else {
pi.playerMessage(5, "The portal is not opened yet.");
return(false);
}
}

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) {
if (pi.getMap().getMonsters().size() == 0) {
if (pi.getMap().getMonsters().size() == 0 && passedGrindMode(pi.getMap(), pi.getEventInstance())) {
pi.warp(925100300,0); //next
return(true);
} 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) {
if (pi.getMap().getMonsters().size() == 0) {
if (pi.getMap().getMonsters().size() == 0 && passedGrindMode(pi.getMap(), pi.getEventInstance())) {
pi.warp(925100400,0); //next
return(true);
} else {

View File

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

View File

@@ -23,11 +23,22 @@
*@Author Jvlaple
*Pirate PQ Reactor
*/
function passedGrindMode(map, eim) {
if(eim.getIntProperty("grindMode") == 0) return true;
return eim.activatedAllReactorsOnMap(map, 2511000, 2517999);
}
function act() {
var eim = rm.getPlayer().getEventInstance();
var now = parseInt(eim.getProperty("openedBoxes"));
var now = eim.getIntProperty("openedBoxes");
var nextNum = now + 1;
eim.setProperty("openedBoxes", nextNum);
eim.setIntProperty("openedBoxes", nextNum);
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() {
var eim = rm.getPlayer().getEventInstance();
var now = parseInt(eim.getProperty("openedChests"));
var now = eim.getIntProperty("openedChests");
var nextNum = now + 1;
eim.setProperty("openedChests", nextNum.toString());
eim.setIntProperty("openedChests", nextNum);
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);
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);
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);
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 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.Swordsman;
import constants.skills.ThunderBreaker;
import net.server.channel.handlers.PartyOperationHandler;
import scripting.item.ItemScriptManager;
import server.maps.MapleMapItem;
@@ -1902,7 +1903,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}, healInterval, healInterval);
}
public void disableDoor() {
public void disableDoorSpawn() {
canDoor = false;
TimerManager.getInstance().schedule(new Runnable() {
@Override
@@ -4803,6 +4804,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
recalcLocalStats();
setMPC(new MaplePartyCharacter(this));
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) {
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_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_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_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.
@@ -53,7 +54,7 @@ public class ServerConstants {
public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped.
public static final boolean USE_ERASE_PET_ON_EXPIRATION = false;//Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll.
public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats.
public static final boolean USE_UNDERLEVELED_EXP_BLOCK = true; //Players 20 levels below the killed mob will gain no experience from defeating it.
public static final boolean USE_UNDERLEVELED_EXP_BLOCK = true; //Players 20 levels below the killed mob will gain no experience from defeating it.
//Server Rates And Experience
public static final int EXP_RATE = 10;

View File

@@ -30,11 +30,38 @@ import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleCharacter;
import client.MapleClient;
import constants.ServerConstants;
import scripting.event.EventInstanceManager;
import server.maps.MapleMap;
public final class PartyOperationHandler extends AbstractMaplePacketHandler {
public static void leaveParty(MapleParty party, MaplePartyCharacter partyplayer, MapleClient c) {
World world = c.getWorldServer();
MapleCharacter player = c.getPlayer();
if (party != null && partyplayer != null) {
if (partyplayer.getId() == party.getLeaderId()) {
c.getWorldServer().removeMapPartyMembers(party.getId());
world.updateParty(party.getId(), PartyOperation.DISBAND, partyplayer);
if (player.getEventInstance() != null) {
player.getEventInstance().disbandParty();
}
} else {
player.getMap().removePartyMember(player);
world.updateParty(party.getId(), PartyOperation.LEAVE, partyplayer);
if (player.getEventInstance() != null) {
player.getEventInstance().leftParty(player);
}
}
player.setParty(null);
}
}
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int operation = slea.readByte();
MapleCharacter player = c.getPlayer();
@@ -43,46 +70,28 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
MaplePartyCharacter partyplayer = player.getMPC();
switch (operation) {
case 1: { // create
if(player.getLevel() < 10) {
c.announce(MaplePacketCreator.partyStatusMessage(10));
return;
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));
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 (partyplayer.getId() == party.getLeaderId()) {
c.getWorldServer().removeMapPartyMembers(party.getId());
world.updateParty(party.getId(), PartyOperation.DISBAND, partyplayer);
if (player.getEventInstance() != null) {
player.getEventInstance().disbandParty();
}
} else {
player.getMap().removePartyMember(player);
world.updateParty(party.getId(), PartyOperation.LEAVE, partyplayer);
if (player.getEventInstance() != null) {
player.getEventInstance().leftParty(player);
}
}
player.setParty(null);
}
case 2: { // leave/disband
leaveParty(party, partyplayer, c);
break;
}
case 3: {//join
case 3: { // join
int partyid = slea.readInt();
if (c.getPlayer().getParty() == null) {
party = world.getParty(partyid);
@@ -105,16 +114,26 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
}
break;
}
case 4: {//invite
case 4: { // invite
String name = slea.readMapleAsciiString();
MapleCharacter invited = world.getPlayerStorage().getCharacterByName(name);
if (invited != null) {
if(invited.getLevel() < 10) { //min requirement is level 10
c.announce(MaplePacketCreator.serverNotice(5, "The player you have invited does not meet the requirements."));
return;
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."));
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 (player.getParty() == null) {
if(player.getLevel() < 10 && !ServerConstants.USE_PARTY_FOR_STARTERS) {
c.announce(MaplePacketCreator.partyStatusMessage(10));
return;
}
partyplayer = new MaplePartyCharacter(player);
party = world.createParty(partyplayer);
player.setParty(party);
@@ -158,7 +177,7 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
}
break;
}
case 6: {
case 6: { // change leader
int newLeader = slea.readInt();
MaplePartyCharacter newLeadr = party.getMemberById(newLeader);
world.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, newLeadr);

View File

@@ -21,6 +21,7 @@
*/
package net.server.world;
import client.MapleClient;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
@@ -195,6 +196,24 @@ public class MapleParty {
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
public int hashCode() {
final int prime = 31;

View File

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

View File

@@ -400,8 +400,8 @@ public class World {
chr.setParty(null);
chr.setMPC(null);
}
default:
break;
default:
break;
}
}

View File

@@ -34,6 +34,8 @@ import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;
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.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -50,6 +52,7 @@ import server.expeditions.MapleExpedition;
import server.life.MapleMonster;
import server.maps.MapleMap;
import server.maps.MapleMapFactory;
import server.maps.MapleReactor;
import tools.DatabaseConnection;
import client.MapleCharacter;
import client.SkillFactory;
@@ -87,6 +90,8 @@ public class EventInstanceManager {
private List<Integer> mapIds = new LinkedList<Integer>();
private List<Boolean> isInstanced = new LinkedList<Boolean>();
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 WriteLock wL = mutex.writeLock();
private ScheduledFuture<?> event_schedule = null;
@@ -225,7 +230,13 @@ public class EventInstanceManager {
}
chr.setEventInstance(this);
em.getIv().invokeFunction("playerEntry", this, chr);
sL.lock();
try {
em.getIv().invokeFunction("playerEntry", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -237,7 +248,13 @@ public class EventInstanceManager {
}
try {
unregisterPlayer(chr);
em.getIv().invokeFunction("playerExit", this, chr);
sL.lock();
try {
em.getIv().invokeFunction("playerExit", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -268,7 +285,13 @@ public class EventInstanceManager {
public void run() {
try {
dismissEventTimer();
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
sL.lock();
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -286,7 +309,13 @@ public class EventInstanceManager {
public void run() {
try {
dismissEventTimer();
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
sL.lock();
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -354,7 +383,12 @@ public class EventInstanceManager {
public void unregisterPlayer(MapleCharacter chr) {
try {
em.getIv().invokeFunction("playerUnregistered", EventInstanceManager.this, chr);
sL.lock();
try {
em.getIv().invokeFunction("playerUnregistered", EventInstanceManager.this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -409,7 +443,12 @@ public class EventInstanceManager {
public void movePlayer(MapleCharacter chr) {
try {
em.getIv().invokeFunction("moveMap", this, chr);
sL.lock();
try {
em.getIv().invokeFunction("moveMap", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -417,19 +456,34 @@ public class EventInstanceManager {
public void changedMap(MapleCharacter chr, int mapId) { // optional
try {
em.getIv().invokeFunction("changedMap", this, chr, mapId);
sL.lock();
try {
em.getIv().invokeFunction("changedMap", this, chr, mapId);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {}
}
public void afterChangedMap(MapleCharacter chr, int mapId) { // optional
try {
em.getIv().invokeFunction("afterChangedMap", this, chr, mapId);
sL.lock();
try {
em.getIv().invokeFunction("afterChangedMap", this, chr, mapId);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {}
}
public void changedLeader(MapleCharacter ldr) {
try {
em.getIv().invokeFunction("changedLeader", this, ldr);
sL.lock();
try {
em.getIv().invokeFunction("changedLeader", this, ldr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -440,13 +494,23 @@ public class EventInstanceManager {
public void monsterKilled(MapleMonster mob) {
mobs.remove(mob);
try {
em.getIv().invokeFunction("monsterKilled", mob, this);
sL.lock();
try {
em.getIv().invokeFunction("monsterKilled", mob, this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
if (mobs.isEmpty()) {
try {
em.getIv().invokeFunction("allMonstersDead", this);
sL.lock();
try {
em.getIv().invokeFunction("allMonstersDead", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -455,7 +519,12 @@ public class EventInstanceManager {
public void friendlyKilled(MapleMonster mob) {
try {
em.getIv().invokeFunction("friendlyKilled", mob, this);
sL.lock();
try {
em.getIv().invokeFunction("friendlyKilled", mob, this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
//optional
}
@@ -463,7 +532,12 @@ public class EventInstanceManager {
public void playerKilled(MapleCharacter chr) {
try {
em.getIv().invokeFunction("playerDead", this, chr);
sL.lock();
try {
em.getIv().invokeFunction("playerDead", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -471,7 +545,15 @@ public class EventInstanceManager {
public boolean revivePlayer(MapleCharacter chr) {
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) {
return (Boolean) b;
}
@@ -483,7 +565,12 @@ public class EventInstanceManager {
public void playerDisconnected(MapleCharacter chr) {
try {
em.getIv().invokeFunction("playerDisconnected", this, chr);
sL.lock();
try {
em.getIv().invokeFunction("playerDisconnected", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -497,7 +584,15 @@ public class EventInstanceManager {
public void monsterKilled(MapleCharacter chr, MapleMonster mob) {
try {
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) {
kc = inc;
} else {
@@ -526,7 +621,12 @@ public class EventInstanceManager {
public void dispose() {
try {
em.getIv().invokeFunction("dispose", this);
sL.lock();
try {
em.getIv().invokeFunction("dispose", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -563,7 +663,12 @@ public class EventInstanceManager {
if(em == null) return;
try {
em.getIv().invokeFunction(methodName, EventInstanceManager.this);
sL.lock();
try {
em.getIv().invokeFunction(methodName, EventInstanceManager.this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -613,28 +718,49 @@ public class EventInstanceManager {
}
public void setProperty(String key, String value) {
props.setProperty(key, value);
pL.lock();
try {
props.setProperty(key, value);
} finally {
pL.unlock();
}
}
public Object setProperty(String key, String value, boolean prev) {
return props.setProperty(key, value);
pL.lock();
try {
return props.setProperty(key, value);
} finally {
pL.unlock();
}
}
public String getProperty(String key) {
return props.getProperty(key);
pL.lock();
try {
return props.getProperty(key);
} finally {
pL.unlock();
}
}
public Properties getProperties() {
return props;
}
public int getIntProperty(String key) {
return Integer.parseInt(props.getProperty(key));
pL.lock();
try {
return Integer.parseInt(props.getProperty(key));
} finally {
pL.unlock();
}
}
public void leftParty(MapleCharacter chr) {
try {
em.getIv().invokeFunction("leftParty", this, chr);
sL.lock();
try {
em.getIv().invokeFunction("leftParty", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -642,7 +768,12 @@ public class EventInstanceManager {
public void disbandParty() {
try {
em.getIv().invokeFunction("disbandParty", this);
sL.lock();
try {
em.getIv().invokeFunction("disbandParty", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -650,7 +781,12 @@ public class EventInstanceManager {
public void clearPQ() {
try {
em.getIv().invokeFunction("clearPQ", this);
sL.lock();
try {
em.getIv().invokeFunction("clearPQ", this);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -658,7 +794,12 @@ public class EventInstanceManager {
public void removePlayer(MapleCharacter chr) {
try {
em.getIv().invokeFunction("playerExit", this, chr);
sL.lock();
try {
em.getIv().invokeFunction("playerExit", this, chr);
} finally {
sL.unlock();
}
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -1140,4 +1281,20 @@ public class EventInstanceManager {
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;
}
if (!ItemConstants.isCleanSlate(scrollId)) {
if (!assertGM && !usingWhiteScroll) {
if (!assertGM) {
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
}
nEquip.setLevel((byte) (nEquip.getLevel() + 1));

View File

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

View File

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

View File

@@ -1338,6 +1338,27 @@ public class MapleMap {
objectRLock.unlock();
}
}
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) {
objectRLock.lock();
@@ -1607,7 +1628,7 @@ public class MapleMap {
try {
List<MaplePortal> availablePortals = new ArrayList<>();
for (MaplePortal port : getPortals()) {
for (MaplePortal port : portals.values()) {
if (port.getType() == MaplePortal.DOOR_PORTAL) {
availablePortals.add(port);
}
@@ -2117,9 +2138,11 @@ public class MapleMap {
return null;
}
/*
public Collection<MaplePortal> getPortals() {
return Collections.unmodifiableCollection(portals.values());
}
*/
public void removePlayer(MapleCharacter chr) {
chrWLock.lock();