Services unrestrained to channels + Event scripts placeholder
Fixed an inconsistent scenario where player data would remain in world player storage even though they were no longer online. Implemented missing functionality for "Safety Charm" which allows 30% MaxHP/MP heal on return. Improved services facility, no longer tightly related to channels. Implemented a world service for "save players" (services acts as a monitor). Reviewed the event script initialization approach. Players no longer are retained from logging in on a channel whilst the events don't finish loadup. Fixed certain quest items not showing up, which would happen due to them not being quest requisites. Fixed NPC Pi crashing players when trying to craft arrows. Fixed pet re-evolution quest not working on Robos. Fixed boss HPBar not disappearing in certain situations. Revised gathered mob info on linked mobs, no longer marshaling stats. Fixed two possible deadlock scenarios within the cancel effect method. Added lock auditing support for read-write locks. Implemented code support for Cygnus intro clip. Reviewed updateBuffEffect, now properly checking for pirate buffs in order to send the expected packet. Reviewed unnecessary load of field objects, which would be doing so just for fetching the predicted map names. Fixed mob buff tooltips not showing on "fake" mobs in the event of them turning into "real". Reviewed usage of "unique" constraint on petid within the inventoryitems table. Fixed portal in Ariant unexpectedly leading players who completed the "secret passageway" of Sleepywood into it. Fixed a loop case in quest scripts from Magatia's broker having ore request.
This commit is contained in:
@@ -2197,3 +2197,40 @@ Adicionado método que permite executar scripts de mapa no sistema de scripts de
|
|||||||
Corrigido problema recente ao referenciar script com progresso "Touch the Sky" (script de portal utilizando métodos de scripts de mapa).
|
Corrigido problema recente ao referenciar script com progresso "Touch the Sky" (script de portal utilizando métodos de scripts de mapa).
|
||||||
Adicionado fallback para scripts de NPC MapleTV.
|
Adicionado fallback para scripts de NPC MapleTV.
|
||||||
Revisado aplicação e abordagem deste código-base nos arquivos XML legado.
|
Revisado aplicação e abordagem deste código-base nos arquivos XML legado.
|
||||||
|
|
||||||
|
15 - 16 Outubro 2019,
|
||||||
|
Corrigido caso inconsistente onde objeto de jogador seria mantido no storage de jogadores caso o jogador tentasse se deregistrar de um canal (sem desconectar) e não mais retornando na mesma sessão.
|
||||||
|
Adicionado código para funcionalidade de "Safety Charm", que permite jogadores curar 30% MaxHP/MaxMP ao retornar em campo.
|
||||||
|
Implementado extensão das facilidades de serviços, agora atuando desjuntamente de canais.
|
||||||
|
Implementado serviço de mundo para salvar jogadores, assim evitando geração de novas threads para cada jogador que está sendo persistido na DB.
|
||||||
|
|
||||||
|
18 Outubro 2019,
|
||||||
|
Revisado abordagem de inicialização de scripts de eventos em canais. Usuários não são mais bloqueados ao tentar logar devido ao canal não ter todos os eventos carregados.
|
||||||
|
|
||||||
|
19 Outubro 2019,
|
||||||
|
Corrigido certos itens de quest não aparecendo de mobs em casos onde o mesmo não é requisito para iniciar/completar.
|
||||||
|
Corrigido NPC Pi crashando jogadores ao tentar criar flechas.
|
||||||
|
Corrigido script de reevolução de pets não atuando em pet Robos, além de agora evitar repetir pets na conversão.
|
||||||
|
|
||||||
|
21 - 22 Outubro 2019,
|
||||||
|
Corrigido boss HPbar não desaparecendo em certos cenários. O mesmo deveria ocorrer assim que mob é retirado do mapa.
|
||||||
|
Revisado informações de mob, que não são propagáveis, sendo repassados à definição do novo mob.
|
||||||
|
Revisado carregamento de storages ao inicializar informações de conta podendo retornar nulo indevidamente em caso de exceção lançada.
|
||||||
|
Corrigido dois casos de deadlock ocorrendo ao tentar cancelar efeito de stat de jogador.
|
||||||
|
Adicionado auditoria de locks para os componentes que travam para leitura e escrita.
|
||||||
|
Adicionado clip de introdução de Cygnus.
|
||||||
|
Revisado updateBuffEffect, agora checando por determinados buffs de pirata e usando pacotes específicos para os mesmos.
|
||||||
|
Revisado geração desnecessária de objetos de mapa ao carregar nomes para comando "goto".
|
||||||
|
Corrigido buffs de mob em fakes desaparecendo assim que o mesmo muda de estado para real.
|
||||||
|
|
||||||
|
24 Outubro 2019,
|
||||||
|
Revisado uso de scriptids na geração de PlayerNPCs. Agora somente ids existentes na base especificada vai adiante.
|
||||||
|
|
||||||
|
27 Outubro 2019,
|
||||||
|
Revisado lógica booleana na detecção de foothold abaixo, não realizando múltiplas checagens sobre um mesmo atributo.
|
||||||
|
|
||||||
|
28 Outubro 2019,
|
||||||
|
Revisado lógica recente de uso de petid único levando a lançamento de exceção (transações de DB implica retirada de item de pet do CS storage na DB antes de colocar o mesmo no inventário).
|
||||||
|
Corrigido portal relacionado a quest em Ariant inesperadamente levando jogadores à passagem secreta de Sleepywood, em caso de conclusão de questline da mesma.
|
||||||
|
Corrigido loop em scripts de quest de associação a Alcadno/Zenumist em Magatia.
|
||||||
|
Adicionado utilização de dispose em quest scripts para o comando homônimo.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <[email protected]>
|
||||||
|
Matthias Butz <[email protected]>
|
||||||
|
Jan Christian Meyer <[email protected]>
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function start(ms) {
|
||||||
|
ms.displayCygnusIntro();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
function start(ms) {
|
||||||
|
if (ms.getJobId() == 1000 && ms.getLevel() >= 10) {
|
||||||
|
ms.unlockUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -72,7 +72,7 @@ function action(mode, type, selection) {
|
|||||||
} else if (status == 2){
|
} else if (status == 2){
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
if (beauty == 1){
|
if (beauty == 1){
|
||||||
if (cm.haveItem(5420002)){
|
if (cm.haveItem(5420002)){ // thanks MedicOP for noticing uncoded functionality for Hair Membership coupons
|
||||||
cm.setHair(hairnew[selection]);
|
cm.setHair(hairnew[selection]);
|
||||||
cm.sendOk("Enjoy your new and improved hairstyle!");
|
cm.sendOk("Enjoy your new and improved hairstyle!");
|
||||||
} else if (cm.haveItem(5150001)){
|
} else if (cm.haveItem(5150001)){
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ function action(mode, type, selection) {
|
|||||||
cm.sendNext("All right! Let's go!");
|
cm.sendNext("All right! Let's go!");
|
||||||
} else if (status == 1) {
|
} else if (status == 1) {
|
||||||
cm.removeNPC(579711);
|
cm.removeNPC(579711);
|
||||||
cm.removeNPC2(579711);
|
|
||||||
cm.updateInfo("fire", "0");
|
cm.updateInfo("fire", "0");
|
||||||
cm.playSound("cannonshooter/fire");
|
cm.playSound("cannonshooter/fire");
|
||||||
cm.sendDirectionInfo("Effect/Direction4.img/effect/cannonshooter/flying/0", 7000, 0, 0, -1, -1);
|
cm.sendDirectionInfo("Effect/Direction4.img/effect/cannonshooter/flying/0", 7000, 0, 0, -1, -1);
|
||||||
|
|||||||
+13
-12
@@ -173,18 +173,6 @@ function action(mode, type, selection) {
|
|||||||
cost = costSet[selectedItem];
|
cost = costSet[selectedItem];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedType == 5){ //arrow refine
|
|
||||||
var itemSet = new Array(2060000,2061000,2060001,2061001,2060002,2061002);
|
|
||||||
var matSet = new Array(new Array (4003001,4003004),new Array (4003001,4003004),new Array (4011000,4003001,4003004),new Array (4011000,4003001,4003004),
|
|
||||||
new Array (4011001,4003001,4003005),new Array (4011001,4003001,4003005));
|
|
||||||
var matQtySet = new Array (new Array (1,1),new Array (1,1),new Array (1,3,10),new Array (1,3,10),new Array (1,5,15),new Array (1,5,15));
|
|
||||||
var costSet = new Array (0,0,0,0,0,0);
|
|
||||||
item = itemSet[selectedItem];
|
|
||||||
mats = matSet[selectedItem];
|
|
||||||
matQty = matQtySet[selectedItem];
|
|
||||||
cost = costSet[selectedItem];
|
|
||||||
}
|
|
||||||
|
|
||||||
var prompt = "So, you want me to make some #t" + item + "#s? In that case, how many do you want me to make?";
|
var prompt = "So, you want me to make some #t" + item + "#s? In that case, how many do you want me to make?";
|
||||||
|
|
||||||
cm.sendGetNumber(prompt,1,1,100)
|
cm.sendGetNumber(prompt,1,1,100)
|
||||||
@@ -198,6 +186,19 @@ function action(mode, type, selection) {
|
|||||||
else
|
else
|
||||||
qty = (selection > 0) ? selection : (selection < 0 ? -selection : 1);
|
qty = (selection > 0) ? selection : (selection < 0 ? -selection : 1);
|
||||||
|
|
||||||
|
// thanks kvmba for noticing arrow selection crashing players
|
||||||
|
if (selectedType == 5){ //arrow refine
|
||||||
|
var itemSet = new Array(2060000,2061000,2060001,2061001,2060002,2061002);
|
||||||
|
var matSet = new Array(new Array (4003001,4003004),new Array (4003001,4003004),new Array (4011000,4003001,4003004),new Array (4011000,4003001,4003004),
|
||||||
|
new Array (4011001,4003001,4003005),new Array (4011001,4003001,4003005));
|
||||||
|
var matQtySet = new Array (new Array (1,1),new Array (1,1),new Array (1,3,10),new Array (1,3,10),new Array (1,5,15),new Array (1,5,15));
|
||||||
|
var costSet = new Array (0,0,0,0,0,0);
|
||||||
|
item = itemSet[selectedItem];
|
||||||
|
mats = matSet[selectedItem];
|
||||||
|
matQty = matQtySet[selectedItem];
|
||||||
|
cost = costSet[selectedItem];
|
||||||
|
}
|
||||||
|
|
||||||
var prompt = "You want me to make ";
|
var prompt = "You want me to make ";
|
||||||
if (qty == 1)
|
if (qty == 1)
|
||||||
prompt += "a #t" + item + "#?";
|
prompt += "a #t" + item + "#?";
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ function writeFeatureTab_Quests() {
|
|||||||
addFeature("3rd job quiz with all 40-question pool available.");
|
addFeature("3rd job quiz with all 40-question pool available.");
|
||||||
addFeature("Item raising functional.");
|
addFeature("Item raising functional.");
|
||||||
addFeature("Cleared issue with player movement during NPC talk.");
|
addFeature("Cleared issue with player movement during NPC talk.");
|
||||||
addFeature("Reviewed usage of quest progress data as requirement.");
|
addFeature("Reviewed usage of quest progress data as requisite.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeFeatureTab_PlayerSocialNetwork() {
|
function writeFeatureTab_PlayerSocialNetwork() {
|
||||||
@@ -287,6 +287,7 @@ function writeFeatureTab_Project() {
|
|||||||
addFeature("Remodeled item scripts, properly using NPC dialogs.");
|
addFeature("Remodeled item scripts, properly using NPC dialogs.");
|
||||||
addFeature("ThreadTracker: runtime tool for deadlock detection.");
|
addFeature("ThreadTracker: runtime tool for deadlock detection.");
|
||||||
addFeature("Channel, World and Server-wide timer management.");
|
addFeature("Channel, World and Server-wide timer management.");
|
||||||
|
addFeature("Developed services as preemptive task scheduler.");
|
||||||
addFeature("Thoroughly reviewed encapsulation for player stats.");
|
addFeature("Thoroughly reviewed encapsulation for player stats.");
|
||||||
addFeature("Heavily reviewed future task management, spawning much less threads and relieving task overload on the TimerManager.");
|
addFeature("Heavily reviewed future task management, spawning much less threads and relieving task overload on the TimerManager.");
|
||||||
}
|
}
|
||||||
@@ -327,7 +328,7 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
var sendStr = "HeavenMS was developed on the timespan of 3 years, based on where Solaxia left. I'm glad to say the development itself had continuously been agraciated by dozens of contributors and cheerers (truly thanks for the trusting vow, guys & gals!).\r\n\r\nTalking about results: many nice features emerged, development aimed to get back the old GMS experience. Now many of these so-long missing features are gracefully presented to you in the shape of this server. Long live MapleStory!!\r\n\r\nThese are the features from #bHeavenMS#k:\r\n\r\n";
|
var sendStr = "HeavenMS was developed on the timespan of 4 years, based on where Solaxia left. I'm glad to say the development itself had continuously been agraciated by dozens of contributors and cheerers (truly thanks for the trusting vow, guys & gals!).\r\n\r\nTalking about results: many nice features emerged, development aimed to get back the old GMS experience. Now many of these so-long missing features are gracefully presented to you in the shape of this server. Long live MapleStory!!\r\n\r\nThese are the features from #bHeavenMS#k:\r\n\r\n";
|
||||||
for(var i = 0; i < tabs.length; i++) {
|
for(var i = 0; i < tabs.length; i++) {
|
||||||
sendStr += "#L" + i + "##b" + tabs[i] + "#k#l\r\n";
|
sendStr += "#L" + i + "##b" + tabs[i] + "#k#l\r\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
// Author: Ronan
|
// Author: Ronan
|
||||||
function enter(ms) {
|
function enter(ms) {
|
||||||
|
// thanks kvmba for noticing some issues running this script
|
||||||
ms.runMapScript();
|
ms.runMapScript();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
function enter(pi) {
|
function enter(pi) {
|
||||||
if(pi.isQuestCompleted(20730) || pi.isQuestCompleted(21734)) { // puppeteer defeated, newfound secret path
|
// unexpected warp condition noticed thanks to IxianMace
|
||||||
pi.playPortalSound(); pi.warp(105040201,2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pi.openNpc(1063011, "ThiefPassword");
|
pi.openNpc(1063011, "ThiefPassword");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function start(mode, type, selection) {
|
|||||||
} else if (status == 4) {
|
} else if (status == 4) {
|
||||||
qm.forceStartQuest();
|
qm.forceStartQuest();
|
||||||
qm.forceCompleteQuest();
|
qm.forceCompleteQuest();
|
||||||
//qm.warp(913040100, 0);
|
qm.warp(913040100, 0);
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-11
@@ -28,32 +28,39 @@
|
|||||||
var status = -1;
|
var status = -1;
|
||||||
var oreArray;
|
var oreArray;
|
||||||
|
|
||||||
function start(mode, type, selection) {
|
|
||||||
}
|
|
||||||
|
|
||||||
function end(mode, type, selection) {
|
function end(mode, type, selection) {
|
||||||
if (mode == -1 || (mode == 0 && type > 0)) {
|
if (mode == -1) {
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
} else {
|
} else {
|
||||||
oreArray = getOreArray();
|
if (mode == 0 && type > 0) {
|
||||||
if (status == -1) {
|
qm.dispose();
|
||||||
if (oreArray.length > 0) {
|
return;
|
||||||
|
}
|
||||||
|
if (mode == 1)
|
||||||
status++;
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
oreArray = getOreArray();
|
||||||
|
if (oreArray.length > 0) {
|
||||||
qm.sendSimple("Oh, looks like someone's ready to make a deal. You want to join Zenumist so badly, huh? I really don't understand you, but that's just fine. What will you give me in return?\r\n" + getOreString(oreArray));
|
qm.sendSimple("Oh, looks like someone's ready to make a deal. You want to join Zenumist so badly, huh? I really don't understand you, but that's just fine. What will you give me in return?\r\n" + getOreString(oreArray));
|
||||||
} else {
|
} else {
|
||||||
qm.sendOk("What is this, you don't have the ores with you. No ore, no deal.");
|
qm.sendOk("What is this, you don't have the #rjewel ores#k with you. No ore, no deal.");
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else if (status == 0) {
|
} else if (status == 1) {
|
||||||
if (!qm.haveItem(oreArray[selection], 2)) {
|
if (!qm.haveItem(oreArray[selection], 2)) {
|
||||||
qm.sendNext("What's this, you haven't got the ores. No ores no deal!");
|
qm.sendNext("What's this, you haven't got the #rjewel ores#k. No ores no deal!");
|
||||||
|
qm.dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qm.gainItem(oreArray[selection], -2); // Take 2 ores
|
qm.gainItem(oreArray[selection], -2); // Take 2 ores
|
||||||
qm.sendNext("Then wait for awhile. I'll go and get the stuff to help you pass the test of Chief Zenumist.");
|
qm.sendNext("Then wait for awhile. I'll go and get the stuff to help you pass the test of Chief Zenumist.");
|
||||||
qm.forceCompleteQuest();
|
qm.forceCompleteQuest();
|
||||||
} else if (status == 1) {
|
} else if (status == 2) {
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-15
@@ -28,32 +28,39 @@
|
|||||||
var status = -1;
|
var status = -1;
|
||||||
var oreArray;
|
var oreArray;
|
||||||
|
|
||||||
function start(mode, type, selection) {
|
|
||||||
}
|
|
||||||
|
|
||||||
function end(mode, type, selection) {
|
function end(mode, type, selection) {
|
||||||
if (mode == -1 || (mode == 0 && type > 0)) {
|
if (mode == -1) {
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
} else {
|
} else {
|
||||||
oreArray = getOreArray();
|
if (mode == 0 && type > 0) {
|
||||||
if (status == -1) {
|
|
||||||
if (oreArray.length > 0) {
|
|
||||||
status++;
|
|
||||||
qm.sendSimple("Oh, looks like someone's ready to make a deal. You want to join Alcadno so badly, huh? I really don't understand you, but that's just fine. What will you give me in return?\r\n" + getOreString(oreArray));
|
|
||||||
} else {
|
|
||||||
qm.sendOk("What is this, you don't have the ores with you. No ore, no deal.");
|
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else if (status == 0) {
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
oreArray = getOreArray();
|
||||||
|
if (oreArray.length > 0) {
|
||||||
|
qm.sendSimple("Oh, looks like someone's ready to make a deal. You want to join Zenumist so badly, huh? I really don't understand you, but that's just fine. What will you give me in return?\r\n" + getOreString(oreArray));
|
||||||
|
} else {
|
||||||
|
qm.sendOk("What is this, you don't have the #rjewel ores#k with you. No ore, no deal."); // script would loop undefinitely at completion, thanks IxianMace for noticing
|
||||||
|
qm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (status == 1) {
|
||||||
if (!qm.haveItem(oreArray[selection], 2)) { // thanks resinate for noticing a function missing here
|
if (!qm.haveItem(oreArray[selection], 2)) { // thanks resinate for noticing a function missing here
|
||||||
qm.sendNext("What's this, you haven't got the ores. No ores no deal!");
|
qm.sendNext("What's this, you haven't got the #rjewel ores#k. No ores no deal!");
|
||||||
|
qm.dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qm.gainItem(oreArray[selection], -2); // Take 2 ores
|
qm.gainItem(oreArray[selection], -2); // Take 2 ores
|
||||||
qm.sendNext("Then wait for awhile. I'll go and get the stuff to help you pass the test of Chief Alcadno.");
|
qm.sendNext("Then wait for awhile. I'll go and get the stuff to help you pass the test of Chief Zenumist.");
|
||||||
qm.forceCompleteQuest();
|
qm.forceCompleteQuest();
|
||||||
} else if (status == 1) {
|
} else if (status == 2) {
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-23
@@ -47,39 +47,46 @@ function end(mode, type, selection) {
|
|||||||
} else if (status == 1) {
|
} else if (status == 1) {
|
||||||
qm.sendNextPrev("Then here we go...! #rHYAHH!#k");
|
qm.sendNextPrev("Then here we go...! #rHYAHH!#k");
|
||||||
} else if (status == 2) {
|
} else if (status == 2) {
|
||||||
var pet = 0;
|
var petidx = -1;
|
||||||
if (qm.getPlayer().getPet(0).getItemId() >= 5000029 && qm.getPlayer().getPet(0).getItemId() <= 5000033) {
|
var petItemid;
|
||||||
var pet = 0;
|
for (var i = 0; i < 3; i++) {
|
||||||
} else if (qm.getPlayer().getPet(1).getItemId() >= 5000029 && qm.getPlayer().getPet(1).getItemId() <= 5000033) {
|
var pet = qm.getPlayer().getPet(pet);
|
||||||
var pet = 1;
|
if (pet != null) {
|
||||||
} else if (qm.getPlayer().getPet(2).getItemId() >= 5000029 && qm.getPlayer().getPet(2).getItemId() <= 5000033) {
|
var id = pet.getItemId();
|
||||||
var pet = 2;
|
if (id >= 5000029 && id <= 5000033) {
|
||||||
} else {
|
petItemid = 5000030;
|
||||||
|
petidx = i;
|
||||||
|
break;
|
||||||
|
} else if (id >= 5000048 && id <= 5000053) { // thanks Conrad for noticing Robo pets not being able to re-evolve
|
||||||
|
petItemid = 5000049;
|
||||||
|
petidx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (petidx == -1) {
|
||||||
qm.sendOk("Something wrong, try again.");
|
qm.sendOk("Something wrong, try again.");
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var id = qm.getPlayer().getPet(pet).getItemId();
|
|
||||||
if (id < 5000029 || id > 5000033) {
|
var pool = (petItemid == 5000030) ? 10 : 11;
|
||||||
qm.sendOk("Something wrong, try again.");
|
do {
|
||||||
qm.dispose();
|
var rand = 1 + Math.floor(Math.random() * pool);
|
||||||
return;
|
|
||||||
}
|
|
||||||
var rand = 1 + Math.floor(Math.random() * 10);
|
|
||||||
var after = 0;
|
var after = 0;
|
||||||
if (rand >= 1 && rand <= 3) {
|
if (rand >= 1 && rand <= 3) {
|
||||||
after = 5000030;
|
after = petItemid;
|
||||||
} else if (rand >= 4 && rand <= 6) {
|
} else if (rand >= 4 && rand <= 6) {
|
||||||
after = 5000031;
|
after = petItemid + 1;
|
||||||
} else if (rand >= 7 && rand <= 9) {
|
} else if (rand >= 7 && rand <= 9) {
|
||||||
after = 5000032;
|
after = petItemid + 2;
|
||||||
} else if (rand == 10) {
|
} else if (rand == 10) {
|
||||||
after = 5000033;
|
after = petItemid + 3;
|
||||||
} else {
|
} else {
|
||||||
qm.sendOk("Something wrong. Try again.");
|
after = petItemid + 4;
|
||||||
qm.dispose();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} while (after == pet.getItemId());
|
||||||
|
|
||||||
/*if (name.equals(MapleItemInformationProvider.getInstance().getName(id))) {
|
/*if (name.equals(MapleItemInformationProvider.getInstance().getName(id))) {
|
||||||
name = MapleItemInformationProvider.getInstance().getName(after);
|
name = MapleItemInformationProvider.getInstance().getName(after);
|
||||||
@@ -87,7 +94,7 @@ function end(mode, type, selection) {
|
|||||||
|
|
||||||
qm.gainMeso(-10000);
|
qm.gainMeso(-10000);
|
||||||
qm.gainItem(5380000, -1);
|
qm.gainItem(5380000, -1);
|
||||||
qm.evolvePet(pet, after);
|
qm.evolvePet(petidx, after);
|
||||||
|
|
||||||
qm.sendOk("Woo! It worked again! #rYou may find your new pet under your 'CASH' inventory.\r #kIt used to be a #b#i" + id + "##t" + id + "##k, and now it's \r a#b #i" + after + "##t" + after + "##k! \r\n Come back with 10,000 mesos and another Rock of Evolution if you don't like it!\r\n\r\n#fUI/UIWindow.img/QuestIcon/4/0#\r\n#v"+after+"# #t"+after+"#");
|
qm.sendOk("Woo! It worked again! #rYou may find your new pet under your 'CASH' inventory.\r #kIt used to be a #b#i" + id + "##t" + id + "##k, and now it's \r a#b #i" + after + "##t" + after + "##k! \r\n Come back with 10,000 mesos and another Rock of Evolution if you don't like it!\r\n\r\n#fUI/UIWindow.img/QuestIcon/4/0#\r\n#v"+after+"# #t"+after+"#");
|
||||||
} else if (status == 3) {
|
} else if (status == 3) {
|
||||||
|
|||||||
+2
-2
@@ -12968,7 +12968,7 @@ CREATE TABLE IF NOT EXISTS `inventoryitems` (
|
|||||||
`position` int(11) NOT NULL DEFAULT '0',
|
`position` int(11) NOT NULL DEFAULT '0',
|
||||||
`quantity` int(11) NOT NULL DEFAULT '0',
|
`quantity` int(11) NOT NULL DEFAULT '0',
|
||||||
`owner` tinytext NOT NULL,
|
`owner` tinytext NOT NULL,
|
||||||
`petid` int(11) unsigned UNIQUE DEFAULT NULL,
|
`petid` int(11) NOT NULL DEFAULT '-1',
|
||||||
`flag` int(11) NOT NULL,
|
`flag` int(11) NOT NULL,
|
||||||
`expiration` bigint(20) NOT NULL DEFAULT '-1',
|
`expiration` bigint(20) NOT NULL DEFAULT '-1',
|
||||||
`giftFrom` varchar(26) NOT NULL,
|
`giftFrom` varchar(26) NOT NULL,
|
||||||
@@ -16473,7 +16473,7 @@ CREATE TABLE IF NOT EXISTS `pets` (
|
|||||||
PRIMARY KEY (`petid`)
|
PRIMARY KEY (`petid`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||||
|
|
||||||
ALTER TABLE `inventoryitems` ADD CONSTRAINT `fk_itempetid` FOREIGN KEY (`petid`) REFERENCES `pets` (`petid`) ON DELETE SET NULL ;
|
ALTER TABLE `inventoryitems` ADD CONSTRAINT `fk_itempetid` FOREIGN KEY (`petid`) REFERENCES `pets` (`petid`) ON DELETE SET NULL ; # thanks Optimist for noticing queries over petid taking too long, shavit for pointing out an improvement using foreign key
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `petignores` (
|
CREATE TABLE IF NOT EXISTS `petignores` (
|
||||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
|||||||
@@ -21,17 +21,17 @@ package client;
|
|||||||
|
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import constants.game.GameConstants;
|
import constants.game.GameConstants;
|
||||||
import constants.net.ServerConstants;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import server.maps.AbstractAnimatedMapleMapObject;
|
import server.maps.AbstractAnimatedMapleMapObject;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
|
|
||||||
@@ -51,13 +51,13 @@ public abstract class AbstractMapleCharacterObject extends AbstractAnimatedMaple
|
|||||||
protected Map<MapleStat, Integer> statUpdates = new HashMap<>();
|
protected Map<MapleStat, Integer> statUpdates = new HashMap<>();
|
||||||
|
|
||||||
protected Lock effLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_EFF, true);
|
protected Lock effLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_EFF, true);
|
||||||
protected ReadLock statRlock;
|
protected MonitoredReadLock statRlock;
|
||||||
protected WriteLock statWlock;
|
protected MonitoredWriteLock statWlock;
|
||||||
|
|
||||||
protected AbstractMapleCharacterObject() {
|
protected AbstractMapleCharacterObject() {
|
||||||
ReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.CHARACTER_STA, true);
|
MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.CHARACTER_STA, true);
|
||||||
statRlock = locks.readLock();
|
statRlock = MonitoredReadLockFactory.createLock(locks);
|
||||||
statWlock = locks.writeLock();
|
statWlock = MonitoredWriteLockFactory.createLock(locks);
|
||||||
|
|
||||||
for (int i = 0; i < remainingSp.length; i++) {
|
for (int i = 0; i < remainingSp.length; i++) {
|
||||||
remainingSp[i] = 0;
|
remainingSp[i] = 0;
|
||||||
|
|||||||
@@ -171,9 +171,11 @@ import constants.skills.Shadower;
|
|||||||
import constants.skills.Sniper;
|
import constants.skills.Sniper;
|
||||||
import constants.skills.Warrior;
|
import constants.skills.Warrior;
|
||||||
import constants.skills.ThunderBreaker;
|
import constants.skills.ThunderBreaker;
|
||||||
import net.server.channel.services.ServiceType;
|
import net.server.services.type.ChannelServices;
|
||||||
import net.server.channel.services.task.BaseService;
|
import net.server.services.task.channel.FaceExpressionService;
|
||||||
import net.server.channel.services.task.FaceExpressionService;
|
import net.server.services.task.world.CharacterSaveService;
|
||||||
|
import net.server.services.type.WorldServices;
|
||||||
|
import org.apache.mina.core.session.IoSession;
|
||||||
import org.apache.mina.util.ConcurrentHashSet;
|
import org.apache.mina.util.ConcurrentHashSet;
|
||||||
|
|
||||||
public class MapleCharacter extends AbstractMapleCharacterObject {
|
public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||||
@@ -214,6 +216,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
private int localchairrate;
|
private int localchairrate;
|
||||||
private boolean hidden, equipchanged = true, berserk, hasMerchant, hasSandboxItem = false, whiteChat = false, canRecvPartySearchInvite = true;
|
private boolean hidden, equipchanged = true, berserk, hasMerchant, hasSandboxItem = false, whiteChat = false, canRecvPartySearchInvite = true;
|
||||||
private boolean equippedMesoMagnet = false, equippedItemPouch = false, equippedPetItemIgnore = false;
|
private boolean equippedMesoMagnet = false, equippedItemPouch = false, equippedPetItemIgnore = false;
|
||||||
|
private boolean usedSafetyCharm = false;
|
||||||
private float autopotHpAlert, autopotMpAlert;
|
private float autopotHpAlert, autopotMpAlert;
|
||||||
private int linkedLevel = 0;
|
private int linkedLevel = 0;
|
||||||
private String linkedName = null;
|
private String linkedName = null;
|
||||||
@@ -565,7 +568,9 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setSessionTransitionState() {
|
public void setSessionTransitionState() {
|
||||||
client.getSession().setAttribute(MapleClient.CLIENT_TRANSITION);
|
IoSession session = client.getSession();
|
||||||
|
session.setAttribute(MapleClient.CLIENT_TRANSITION);
|
||||||
|
Server.getInstance().setCharacteridInTransition(session, this.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getCS() {
|
public boolean getCS() {
|
||||||
@@ -2846,7 +2851,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
if(timeNow - lastExpression > 2000) {
|
if(timeNow - lastExpression > 2000) {
|
||||||
lastExpression = timeNow;
|
lastExpression = timeNow;
|
||||||
|
|
||||||
FaceExpressionService service = (FaceExpressionService) client.getChannelServer().getServiceAccess(ServiceType.FACE_EXPRESSION);
|
FaceExpressionService service = (FaceExpressionService) client.getChannelServer().getServiceAccess(ChannelServices.FACE_EXPRESSION);
|
||||||
service.registerFaceExpression(map, this, emote);
|
service.registerFaceExpression(map, this, emote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3863,11 +3868,13 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
public boolean cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
|
public boolean cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
|
||||||
boolean ret;
|
boolean ret;
|
||||||
|
|
||||||
|
prtLock.lock();
|
||||||
effLock.lock();
|
effLock.lock();
|
||||||
try {
|
try {
|
||||||
ret = cancelEffect(effect, overwrite, startTime, true);
|
ret = cancelEffect(effect, overwrite, startTime, true);
|
||||||
} finally {
|
} finally {
|
||||||
effLock.unlock();
|
effLock.unlock();
|
||||||
|
prtLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effect.isMagicDoor() && ret) {
|
if (effect.isMagicDoor() && ret) {
|
||||||
@@ -4580,6 +4587,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
startChairTask();
|
startChairTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prtLock.lock();
|
||||||
effLock.lock();
|
effLock.lock();
|
||||||
chrLock.lock();
|
chrLock.lock();
|
||||||
try {
|
try {
|
||||||
@@ -4596,7 +4604,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
toDeploy = new LinkedHashMap<>();
|
toDeploy = new LinkedHashMap<>();
|
||||||
Map<Integer, Pair<MapleStatEffect, Long>> retrievedEffects = new LinkedHashMap<>();
|
Map<Integer, Pair<MapleStatEffect, Long>> retrievedEffects = new LinkedHashMap<>();
|
||||||
Set<MapleBuffStat> retrievedStats = new LinkedHashSet<>();
|
Set<MapleBuffStat> retrievedStats = new LinkedHashSet<>();
|
||||||
|
|
||||||
for (Entry<MapleBuffStat, MapleBuffStatValueHolder> statup : appliedStatups.entrySet()) {
|
for (Entry<MapleBuffStat, MapleBuffStatValueHolder> statup : appliedStatups.entrySet()) {
|
||||||
MapleBuffStatValueHolder mbsvh = effects.get(statup.getKey());
|
MapleBuffStatValueHolder mbsvh = effects.get(statup.getKey());
|
||||||
MapleBuffStatValueHolder statMbsvh = statup.getValue();
|
MapleBuffStatValueHolder statMbsvh = statup.getValue();
|
||||||
@@ -4655,6 +4662,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
} finally {
|
} finally {
|
||||||
chrLock.unlock();
|
chrLock.unlock();
|
||||||
effLock.unlock();
|
effLock.unlock();
|
||||||
|
prtLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLocalStats();
|
updateLocalStats();
|
||||||
@@ -5854,13 +5862,19 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
int amountNeeded, questStatus = this.getQuestStatus(questid);
|
int amountNeeded, questStatus = this.getQuestStatus(questid);
|
||||||
if (questStatus == 0) {
|
if (questStatus == 0) {
|
||||||
amountNeeded = MapleQuest.getInstance(questid).getStartItemAmountNeeded(itemid);
|
amountNeeded = MapleQuest.getInstance(questid).getStartItemAmountNeeded(itemid);
|
||||||
|
if (amountNeeded == Integer.MIN_VALUE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (questStatus != 1) {
|
} else if (questStatus != 1) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
amountNeeded = MapleQuest.getInstance(questid).getCompleteItemAmountNeeded(itemid);
|
amountNeeded = MapleQuest.getInstance(questid).getCompleteItemAmountNeeded(itemid);
|
||||||
|
if (amountNeeded == Integer.MAX_VALUE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return amountNeeded > 0 && getInventory(ItemConstants.getInventoryType(itemid)).countById(itemid) < amountNeeded;
|
return getInventory(ItemConstants.getInventoryType(itemid)).countById(itemid) < amountNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRank() {
|
public int getRank() {
|
||||||
@@ -6208,6 +6222,8 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
if (timeNow < getNextBuybackTime() && avail) {
|
if (timeNow < getNextBuybackTime() && avail) {
|
||||||
s += "Buyback available in #r" + getTimeRemaining(getNextBuybackTime() - timeNow) + "#k";
|
s += "Buyback available in #r" + getTimeRemaining(getNextBuybackTime() - timeNow) + "#k";
|
||||||
s += "\r\n";
|
s += "\r\n";
|
||||||
|
} else {
|
||||||
|
s += "Buyback #bavailable#k";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showHint(s);
|
this.showHint(s);
|
||||||
@@ -7619,6 +7635,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
if (possesed > 0 && !GameConstants.isDojo(getMapId())) {
|
if (possesed > 0 && !GameConstants.isDojo(getMapId())) {
|
||||||
message("You have used a safety charm, so your EXP points have not been decreased.");
|
message("You have used a safety charm, so your EXP points have not been decreased.");
|
||||||
MapleInventoryManipulator.removeById(client, ItemConstants.getInventoryType(charmID[i]), charmID[i], 1, true, false);
|
MapleInventoryManipulator.removeById(client, ItemConstants.getInventoryType(charmID[i]), charmID[i], 1, true, false);
|
||||||
|
usedSafetyCharm = true;
|
||||||
} else if (getJob() != MapleJob.BEGINNER) { //Hmm...
|
} else if (getJob() != MapleJob.BEGINNER) { //Hmm...
|
||||||
if (!FieldLimit.NO_EXP_DECREASE.check(getMap().getFieldLimit())) { // thanks Conrad for noticing missing FieldLimit check
|
if (!FieldLimit.NO_EXP_DECREASE.check(getMap().getFieldLimit())) { // thanks Conrad for noticing missing FieldLimit check
|
||||||
int XPdummy = ExpTable.getExpNeededForLevel(getLevel());
|
int XPdummy = ExpTable.getExpNeededForLevel(getLevel());
|
||||||
@@ -7715,7 +7732,13 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
changeMap(returnMap);
|
changeMap(returnMap);
|
||||||
|
|
||||||
cancelAllBuffs(false); // thanks Oblivium91 for finding out players still could revive in area and take damage before returning to town
|
cancelAllBuffs(false); // thanks Oblivium91 for finding out players still could revive in area and take damage before returning to town
|
||||||
|
|
||||||
|
if (usedSafetyCharm) { // thanks kvmba for noticing safety charm not providing 30% HP/MP
|
||||||
|
addMPHP((int) Math.ceil(this.getClientMaxHp() * 0.3), (int) Math.ceil(this.getClientMaxMp() * 0.3));
|
||||||
|
} else {
|
||||||
updateHp(50);
|
updateHp(50);
|
||||||
|
}
|
||||||
|
|
||||||
setStance(0);
|
setStance(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8378,7 +8401,8 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ThreadManager.getInstance().newTask(r); //spawns a new thread to deal with this
|
CharacterSaveService service = (CharacterSaveService) getWorldServer().getServiceAccess(WorldServices.SAVE_CHARACTER);
|
||||||
|
service.registerSaveCharacter(this.getId(), r);
|
||||||
} else {
|
} else {
|
||||||
saveCharToDB(true);
|
saveCharToDB(true);
|
||||||
}
|
}
|
||||||
@@ -9958,6 +9982,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
if (qs.getInfoNumber() > 0) {
|
if (qs.getInfoNumber() > 0) {
|
||||||
announceUpdateQuest(DelayedQuestUpdate.UPDATE, qs, true);
|
announceUpdateQuest(DelayedQuestUpdate.UPDATE, qs, true);
|
||||||
}
|
}
|
||||||
|
// reminder: do not reset quest progress of infoNumbers, some quests cannot backtrack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ import org.apache.mina.core.session.IoSession;
|
|||||||
|
|
||||||
import client.inventory.MapleInventoryType;
|
import client.inventory.MapleInventoryType;
|
||||||
import constants.game.GameConstants;
|
import constants.game.GameConstants;
|
||||||
import constants.net.ServerConstants;
|
|
||||||
import scripting.AbstractPlayerInteraction;
|
import scripting.AbstractPlayerInteraction;
|
||||||
import scripting.event.EventInstanceManager;
|
import scripting.event.EventInstanceManager;
|
||||||
import scripting.event.EventManager;
|
import scripting.event.EventManager;
|
||||||
@@ -120,7 +119,8 @@ public class MapleClient {
|
|||||||
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true);
|
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true);
|
||||||
private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true);
|
private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true);
|
||||||
private final Lock announcerLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ANNOUNCER, true);
|
private final Lock announcerLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ANNOUNCER, true);
|
||||||
private static final Lock loginLocks[] = new Lock[200]; // thanks Masterrulax & try2hack for pointing out a bottleneck issue here
|
private static final int lockCount = 200;
|
||||||
|
private static final Lock loginLocks[] = new Lock[lockCount]; // thanks Masterrulax & try2hack for pointing out a bottleneck issue here
|
||||||
private Calendar tempBanCalendar;
|
private Calendar tempBanCalendar;
|
||||||
private int votePoints;
|
private int votePoints;
|
||||||
private int voteTime = -1;
|
private int voteTime = -1;
|
||||||
@@ -131,7 +131,7 @@ public class MapleClient {
|
|||||||
private int lang = 0;
|
private int lang = 0;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < lockCount; i++) {
|
||||||
loginLocks[i] = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_LOGIN, true);
|
loginLocks[i] = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_LOGIN, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,14 +454,14 @@ public class MapleClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int finishLogin() {
|
public int finishLogin() {
|
||||||
Lock loginLock = loginLocks[this.getAccID() % 200];
|
Lock loginLock = loginLocks[this.getAccID() % lockCount];
|
||||||
loginLock.lock();
|
loginLock.lock();
|
||||||
try {
|
try {
|
||||||
if (getLoginState() > LOGIN_NOTLOGGEDIN) { // 0 = LOGIN_NOTLOGGEDIN, 1= LOGIN_SERVER_TRANSITION, 2 = LOGIN_LOGGEDIN
|
if (getLoginState() > LOGIN_NOTLOGGEDIN) { // 0 = LOGIN_NOTLOGGEDIN, 1= LOGIN_SERVER_TRANSITION, 2 = LOGIN_LOGGEDIN
|
||||||
loggedIn = false;
|
loggedIn = false;
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
updateLoginState(LOGIN_LOGGEDIN);
|
updateLoginState(MapleClient.LOGIN_LOGGEDIN);
|
||||||
} finally {
|
} finally {
|
||||||
loginLock.unlock();
|
loginLock.unlock();
|
||||||
}
|
}
|
||||||
@@ -851,7 +851,7 @@ public class MapleClient {
|
|||||||
if (rs.getTimestamp("lastlogin").getTime() + 30000 < Server.getInstance().getCurrentTime()) {
|
if (rs.getTimestamp("lastlogin").getTime() + 30000 < Server.getInstance().getCurrentTime()) {
|
||||||
int accountId = accId;
|
int accountId = accId;
|
||||||
state = LOGIN_NOTLOGGEDIN;
|
state = LOGIN_NOTLOGGEDIN;
|
||||||
updateLoginState(LOGIN_NOTLOGGEDIN); // ACCID = 0, issue found thanks to Tochi & K u ssss o & Thora & Omo Oppa
|
updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN); // ACCID = 0, issue found thanks to Tochi & K u ssss o & Thora & Omo Oppa
|
||||||
this.setAccID(accountId);
|
this.setAccID(accountId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1232,6 +1232,22 @@ public class MapleClient {
|
|||||||
return disconnectForBeingAFaggot;
|
return disconnectForBeingAFaggot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkChar(int accid) { /// issue with multiple chars from same account login found by shavit, resinate
|
||||||
|
if (true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (World w : Server.getInstance().getWorlds()) {
|
||||||
|
for (MapleCharacter chr : w.getPlayerStorage().getAllCharacters()) {
|
||||||
|
if (accid == chr.getAccountID()) {
|
||||||
|
FilePrinter.print(FilePrinter.EXPLOITS, "Player: " + chr.getName() + " has been removed from " + GameConstants.WORLD_NAMES[w.getId()] + ". Possible Dupe attempt.");
|
||||||
|
chr.getClient().forceDisconnect();
|
||||||
|
w.getPlayerStorage().removePlayer(chr.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getVotePoints(){
|
public int getVotePoints(){
|
||||||
int points = 0;
|
int points = 0;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -82,7 +82,9 @@ public final class MonsterBook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(qty < 5) {
|
if(qty < 5) {
|
||||||
calculateLevel(); // current leveling system only accounts unique cards...
|
if (qty == 0) { // leveling system only accounts unique cards
|
||||||
|
calculateLevel();
|
||||||
|
}
|
||||||
|
|
||||||
c.announce(MaplePacketCreator.addCard(false, cardid, qty + 1));
|
c.announce(MaplePacketCreator.addCard(false, cardid, qty + 1));
|
||||||
c.announce(MaplePacketCreator.showGainCard());
|
c.announce(MaplePacketCreator.showGainCard());
|
||||||
@@ -94,7 +96,15 @@ public final class MonsterBook {
|
|||||||
private void calculateLevel() {
|
private void calculateLevel() {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
bookLevel = (int) Math.max(1, Math.sqrt((normalCard + specialCard) / 5));
|
int collectionExp = (normalCard + specialCard);
|
||||||
|
|
||||||
|
int level = 0, expToNextlevel = 1;
|
||||||
|
do {
|
||||||
|
level++;
|
||||||
|
expToNextlevel += level * 10;
|
||||||
|
} while (collectionExp >= expToNextlevel);
|
||||||
|
|
||||||
|
bookLevel = level; // thanks IxianMace for noticing book level differing between book UI and character info UI
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ package client.command.commands.gm0;
|
|||||||
import client.command.Command;
|
import client.command.Command;
|
||||||
import client.MapleClient;
|
import client.MapleClient;
|
||||||
import scripting.npc.NPCScriptManager;
|
import scripting.npc.NPCScriptManager;
|
||||||
|
import scripting.quest.QuestScriptManager;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
|
|
||||||
public class DisposeCommand extends Command {
|
public class DisposeCommand extends Command {
|
||||||
@@ -36,6 +37,7 @@ public class DisposeCommand extends Command {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(MapleClient c, String[] params) {
|
public void execute(MapleClient c, String[] params) {
|
||||||
NPCScriptManager.getInstance().dispose(c);
|
NPCScriptManager.getInstance().dispose(c);
|
||||||
|
QuestScriptManager.getInstance().dispose(c);
|
||||||
c.announce(MaplePacketCreator.enableActions());
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
c.removeClickedNPC();
|
c.removeClickedNPC();
|
||||||
c.getPlayer().message("You've been disposed.");
|
c.getPlayer().message("You've been disposed.");
|
||||||
|
|||||||
@@ -42,21 +42,26 @@ public class MapOwnerClaimCommand extends Command {
|
|||||||
|
|
||||||
if (YamlConfig.config.server.USE_MAP_OWNERSHIP_SYSTEM) {
|
if (YamlConfig.config.server.USE_MAP_OWNERSHIP_SYSTEM) {
|
||||||
if (chr.getEventInstance() == null) {
|
if (chr.getEventInstance() == null) {
|
||||||
|
MapleMap map = chr.getMap();
|
||||||
|
if (map.countBosses() == 0) { // thanks Conrad for suggesting bosses prevent map leasing
|
||||||
MapleMap ownedMap = chr.getOwnedMap(); // thanks Conrad for suggesting not unlease a map as soon as player exits it
|
MapleMap ownedMap = chr.getOwnedMap(); // thanks Conrad for suggesting not unlease a map as soon as player exits it
|
||||||
if (ownedMap != null) {
|
if (ownedMap != null) {
|
||||||
ownedMap.unclaimOwnership(chr);
|
ownedMap.unclaimOwnership(chr);
|
||||||
|
|
||||||
if (chr.getMap() == ownedMap) {
|
if (map == ownedMap) {
|
||||||
chr.dropMessage(5, "This lawn is now free real estate.");
|
chr.dropMessage(5, "This lawn is now free real estate.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chr.getMap().claimOwnership(chr)) {
|
if (map.claimOwnership(chr)) {
|
||||||
chr.dropMessage(5, "You have leased this lawn for a while, until you leave here or after 1 minute of inactivity.");
|
chr.dropMessage(5, "You have leased this lawn for a while, until you leave here or after 1 minute of inactivity.");
|
||||||
} else {
|
} else {
|
||||||
chr.dropMessage(5, "This lawn has already been leased by a player.");
|
chr.dropMessage(5, "This lawn has already been leased by a player.");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
chr.dropMessage(5, "This lawn is currently under a boss siege.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
chr.dropMessage(5, "This lawn cannot be leased.");
|
chr.dropMessage(5, "This lawn cannot be leased.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,10 @@ import client.MapleClient;
|
|||||||
import constants.game.GameConstants;
|
import constants.game.GameConstants;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import net.server.Server;
|
|
||||||
import server.maps.MaplePortal;
|
import server.maps.MaplePortal;
|
||||||
import server.maps.FieldLimit;
|
import server.maps.FieldLimit;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapManager;
|
import server.maps.MapleMapFactory;
|
||||||
import server.maps.MapleMiniDungeonInfo;
|
import server.maps.MapleMiniDungeonInfo;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -47,19 +46,28 @@ public class GotoCommand extends Command {
|
|||||||
{
|
{
|
||||||
setDescription("");
|
setDescription("");
|
||||||
|
|
||||||
MapleMapManager mapManager = Server.getInstance().getWorlds().get(0).getChannels().get(0).getMapFactory();
|
|
||||||
|
|
||||||
List<Entry<String, Integer>> towns = new ArrayList<>(GameConstants.GOTO_TOWNS.entrySet());
|
List<Entry<String, Integer>> towns = new ArrayList<>(GameConstants.GOTO_TOWNS.entrySet());
|
||||||
sortGotoEntries(towns);
|
sortGotoEntries(towns);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// thanks shavit for noticing goto areas getting loaded from wz needlessly, only for the name retrieval
|
||||||
|
|
||||||
for (Map.Entry<String, Integer> e : towns) {
|
for (Map.Entry<String, Integer> e : towns) {
|
||||||
GOTO_TOWNS_INFO += ("'" + e.getKey() + "' - #b" + (mapManager.getMap(e.getValue()).getMapName()) + "#k\r\n");
|
GOTO_TOWNS_INFO += ("'" + e.getKey() + "' - #b" + (MapleMapFactory.loadPlaceName(e.getValue())) + "#k\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Entry<String, Integer>> areas = new ArrayList<>(GameConstants.GOTO_AREAS.entrySet());
|
List<Entry<String, Integer>> areas = new ArrayList<>(GameConstants.GOTO_AREAS.entrySet());
|
||||||
sortGotoEntries(areas);
|
sortGotoEntries(areas);
|
||||||
for (Map.Entry<String, Integer> e : areas) {
|
for (Map.Entry<String, Integer> e : areas) {
|
||||||
GOTO_AREAS_INFO += ("'" + e.getKey() + "' - #b" + (mapManager.getMap(e.getValue()).getMapName()) + "#k\r\n");
|
GOTO_AREAS_INFO += ("'" + e.getKey() + "' - #b" + (MapleMapFactory.loadPlaceName(e.getValue())) + "#k\r\n");
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
GOTO_TOWNS_INFO = "(none)";
|
||||||
|
GOTO_AREAS_INFO = "(none)";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String GOTO_TOWNS_INFO = "";
|
public static String GOTO_TOWNS_INFO = "";
|
||||||
|
|||||||
@@ -127,10 +127,6 @@ public class Item implements Comparable<Item> {
|
|||||||
return petid;
|
return petid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getPetIdForDb() {
|
|
||||||
return petid > -1 ? petid : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Item other) {
|
public int compareTo(Item other) {
|
||||||
if (this.id < other.getItemId()) {
|
if (this.id < other.getItemId()) {
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ public enum ItemFactory {
|
|||||||
ps.setInt(6, item.getPosition());
|
ps.setInt(6, item.getPosition());
|
||||||
ps.setInt(7, item.getQuantity());
|
ps.setInt(7, item.getQuantity());
|
||||||
ps.setString(8, item.getOwner());
|
ps.setString(8, item.getOwner());
|
||||||
ps.setObject(9, item.getPetIdForDb(), java.sql.Types.INTEGER);
|
ps.setInt(9, item.getPetId()); // thanks Daddy Egg for alerting a case of unique petid constraint breach getting raised
|
||||||
ps.setInt(10, item.getFlag());
|
ps.setInt(10, item.getFlag());
|
||||||
ps.setLong(11, item.getExpiration());
|
ps.setLong(11, item.getExpiration());
|
||||||
ps.setString(12, item.getGiftFrom());
|
ps.setString(12, item.getGiftFrom());
|
||||||
@@ -414,7 +414,7 @@ public enum ItemFactory {
|
|||||||
ps.setInt(6, item.getPosition());
|
ps.setInt(6, item.getPosition());
|
||||||
ps.setInt(7, item.getQuantity());
|
ps.setInt(7, item.getQuantity());
|
||||||
ps.setString(8, item.getOwner());
|
ps.setString(8, item.getOwner());
|
||||||
ps.setObject(9, item.getPetIdForDb(), java.sql.Types.INTEGER);
|
ps.setInt(9, item.getPetId());
|
||||||
ps.setInt(10, item.getFlag());
|
ps.setInt(10, item.getFlag());
|
||||||
ps.setLong(11, item.getExpiration());
|
ps.setLong(11, item.getExpiration());
|
||||||
ps.setString(12, item.getGiftFrom());
|
ps.setString(12, item.getGiftFrom());
|
||||||
|
|||||||
@@ -573,7 +573,7 @@ public class GameConstants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isFreeMarketRoom(int mapid) {
|
public static boolean isFreeMarketRoom(int mapid) {
|
||||||
return mapid > 910000000 && mapid < 910000023;
|
return mapid / 1000000 == 910 && mapid > 910000000; // FM rooms subset, thanks to shavit
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMerchantLocked(MapleMap map) {
|
public static boolean isMerchantLocked(MapleMap map) {
|
||||||
|
|||||||
@@ -28,18 +28,19 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
|
|
||||||
public class PlayerStorage {
|
public class PlayerStorage {
|
||||||
private final ReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_STORAGE, true);
|
private final MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_STORAGE, true);
|
||||||
private final Map<Integer, MapleCharacter> storage = new LinkedHashMap<>();
|
private final Map<Integer, MapleCharacter> storage = new LinkedHashMap<>();
|
||||||
private final Map<String, MapleCharacter> nameStorage = new LinkedHashMap<>();
|
private final Map<String, MapleCharacter> nameStorage = new LinkedHashMap<>();
|
||||||
private ReadLock rlock = locks.readLock();
|
private MonitoredReadLock rlock = MonitoredReadLockFactory.createLock(locks);
|
||||||
private WriteLock wlock = locks.writeLock();
|
private MonitoredWriteLock wlock = MonitoredWriteLockFactory.createLock(locks);
|
||||||
|
|
||||||
public void addPlayer(MapleCharacter chr) {
|
public void addPlayer(MapleCharacter chr) {
|
||||||
wlock.lock();
|
wlock.lock();
|
||||||
|
|||||||
+12
-12
@@ -41,15 +41,16 @@ import java.util.Properties;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
|
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import net.server.audit.ThreadTracker;
|
import net.server.audit.ThreadTracker;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
|
|
||||||
import net.MapleServerHandler;
|
import net.MapleServerHandler;
|
||||||
import net.mina.MapleCodecFactory;
|
import net.mina.MapleCodecFactory;
|
||||||
@@ -87,7 +88,6 @@ import client.SkillFactory;
|
|||||||
import client.command.CommandsExecutor;
|
import client.command.CommandsExecutor;
|
||||||
import client.inventory.Item;
|
import client.inventory.Item;
|
||||||
import client.inventory.ItemFactory;
|
import client.inventory.ItemFactory;
|
||||||
import client.inventory.MaplePet;
|
|
||||||
import client.inventory.manipulator.MapleCashidGenerator;
|
import client.inventory.manipulator.MapleCashidGenerator;
|
||||||
import client.newyear.NewYearCardRecord;
|
import client.newyear.NewYearCardRecord;
|
||||||
import constants.inventory.ItemConstants;
|
import constants.inventory.ItemConstants;
|
||||||
@@ -146,13 +146,13 @@ public class Server {
|
|||||||
private final Lock srvLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER);
|
private final Lock srvLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER);
|
||||||
private final Lock disLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER_DISEASES);
|
private final Lock disLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER_DISEASES);
|
||||||
|
|
||||||
private final ReentrantReadWriteLock wldLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_WORLDS, true);
|
private final MonitoredReentrantReadWriteLock wldLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_WORLDS, true);
|
||||||
private final ReadLock wldRLock = wldLock.readLock();
|
private final MonitoredReadLock wldRLock = MonitoredReadLockFactory.createLock(wldLock);
|
||||||
private final WriteLock wldWLock = wldLock.writeLock();
|
private final MonitoredWriteLock wldWLock = MonitoredWriteLockFactory.createLock(wldLock);
|
||||||
|
|
||||||
private final ReentrantReadWriteLock lgnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_LOGIN, true);
|
private final MonitoredReentrantReadWriteLock lgnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_LOGIN, true);
|
||||||
private final ReadLock lgnRLock = lgnLock.readLock();
|
private final MonitoredReadLock lgnRLock = MonitoredReadLockFactory.createLock(lgnLock);
|
||||||
private final WriteLock lgnWLock = lgnLock.writeLock();
|
private final MonitoredWriteLock lgnWLock = MonitoredWriteLockFactory.createLock(lgnLock);
|
||||||
|
|
||||||
private final AtomicLong currentTime = new AtomicLong(0);
|
private final AtomicLong currentTime = new AtomicLong(0);
|
||||||
private long serverCurrentTime = 0;
|
private long serverCurrentTime = 0;
|
||||||
@@ -1897,12 +1897,12 @@ public class Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetServerWorlds();
|
||||||
|
|
||||||
ThreadManager.getInstance().stop();
|
ThreadManager.getInstance().stop();
|
||||||
TimerManager.getInstance().purge();
|
TimerManager.getInstance().purge();
|
||||||
TimerManager.getInstance().stop();
|
TimerManager.getInstance().stop();
|
||||||
|
|
||||||
resetServerWorlds();
|
|
||||||
|
|
||||||
System.out.println("Worlds + Channels are offline.");
|
System.out.println("Worlds + Channels are offline.");
|
||||||
acceptor.unbind();
|
acceptor.unbind();
|
||||||
acceptor = null;
|
acceptor = null;
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public enum MonitoredLockType {
|
|||||||
WORLD_PSHOPS,
|
WORLD_PSHOPS,
|
||||||
WORLD_MERCHS,
|
WORLD_MERCHS,
|
||||||
WORLD_MAPOBJS,
|
WORLD_MAPOBJS,
|
||||||
|
WORLD_SAVECHARS,
|
||||||
WORLD_SUGGEST,
|
WORLD_SUGGEST,
|
||||||
EIM,
|
EIM,
|
||||||
EIM_PARTY,
|
EIM_PARTY,
|
||||||
|
|||||||
@@ -34,9 +34,11 @@ import java.util.Map.Entry;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
|
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import net.server.audit.LockCollector;
|
import net.server.audit.LockCollector;
|
||||||
@@ -64,6 +66,10 @@ import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
|||||||
import org.apache.mina.transport.socket.SocketSessionConfig;
|
import org.apache.mina.transport.socket.SocketSessionConfig;
|
||||||
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
|
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
|
||||||
|
|
||||||
|
import client.MapleCharacter;
|
||||||
|
import net.server.services.ServicesManager;
|
||||||
|
import net.server.services.BaseService;
|
||||||
|
import net.server.services.type.ChannelServices;
|
||||||
import scripting.event.EventScriptManager;
|
import scripting.event.EventScriptManager;
|
||||||
import server.TimerManager;
|
import server.TimerManager;
|
||||||
import server.events.gm.MapleEvent;
|
import server.events.gm.MapleEvent;
|
||||||
@@ -73,13 +79,9 @@ import server.maps.MapleHiredMerchant;
|
|||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapManager;
|
import server.maps.MapleMapManager;
|
||||||
import server.maps.MapleMiniDungeon;
|
import server.maps.MapleMiniDungeon;
|
||||||
|
import server.maps.MapleMiniDungeonInfo;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
import client.MapleCharacter;
|
|
||||||
import net.server.channel.services.ServiceType;
|
|
||||||
import net.server.channel.services.ServicesManager;
|
|
||||||
import net.server.channel.services.task.BaseService;
|
|
||||||
import server.maps.MapleMiniDungeonInfo;
|
|
||||||
|
|
||||||
public final class Channel {
|
public final class Channel {
|
||||||
|
|
||||||
@@ -90,7 +92,7 @@ public final class Channel {
|
|||||||
private String ip, serverMessage;
|
private String ip, serverMessage;
|
||||||
private MapleMapManager mapManager;
|
private MapleMapManager mapManager;
|
||||||
private EventScriptManager eventSM;
|
private EventScriptManager eventSM;
|
||||||
private ServicesManager services = new ServicesManager();
|
private ServicesManager services;
|
||||||
private Map<Integer, MapleHiredMerchant> hiredMerchants = new HashMap<>();
|
private Map<Integer, MapleHiredMerchant> hiredMerchants = new HashMap<>();
|
||||||
private final Map<Integer, Integer> storedVars = new HashMap<>();
|
private final Map<Integer, Integer> storedVars = new HashMap<>();
|
||||||
private Set<Integer> playersAway = new HashSet<>();
|
private Set<Integer> playersAway = new HashSet<>();
|
||||||
@@ -121,9 +123,9 @@ public final class Channel {
|
|||||||
private Set<Integer> ongoingCathedralGuests = null;
|
private Set<Integer> ongoingCathedralGuests = null;
|
||||||
private long ongoingStartTime;
|
private long ongoingStartTime;
|
||||||
|
|
||||||
private ReentrantReadWriteLock merchantLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MERCHANT, true);
|
private MonitoredReentrantReadWriteLock merchantLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MERCHANT, true);
|
||||||
private ReadLock merchRlock = merchantLock.readLock();
|
private MonitoredReadLock merchRlock = MonitoredReadLockFactory.createLock(merchantLock);
|
||||||
private WriteLock merchWlock = merchantLock.writeLock();
|
private MonitoredWriteLock merchWlock = MonitoredWriteLockFactory.createLock(merchantLock);
|
||||||
|
|
||||||
private MonitoredReentrantLock faceLock[] = new MonitoredReentrantLock[YamlConfig.config.server.CHANNEL_LOCKS];
|
private MonitoredReentrantLock faceLock[] = new MonitoredReentrantLock[YamlConfig.config.server.CHANNEL_LOCKS];
|
||||||
|
|
||||||
@@ -155,8 +157,8 @@ public final class Channel {
|
|||||||
eventSM = new EventScriptManager(this, getEvents());
|
eventSM = new EventScriptManager(this, getEvents());
|
||||||
eventSM.init();
|
eventSM.init();
|
||||||
} else {
|
} else {
|
||||||
String[] ev = {};
|
String[] ev = {"0_EXAMPLE"};
|
||||||
eventSM = new EventScriptManager(null, ev);
|
eventSM = new EventScriptManager(this, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
dojoStage = new int[20];
|
dojoStage = new int[20];
|
||||||
@@ -168,7 +170,7 @@ public final class Channel {
|
|||||||
dojoTask[i] = null;
|
dojoTask[i] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
services = new ServicesManager();
|
services = new ServicesManager(ChannelServices.OVERALL);
|
||||||
|
|
||||||
System.out.println(" Channel " + getId() + ": Listening on port " + port);
|
System.out.println(" Channel " + getId() + ": Listening on port " + port);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -184,7 +186,6 @@ public final class Channel {
|
|||||||
eventSM.cancel();
|
eventSM.cancel();
|
||||||
eventSM = null;
|
eventSM = null;
|
||||||
eventSM = new EventScriptManager(this, getEvents());
|
eventSM = new EventScriptManager(this, getEvents());
|
||||||
eventSM.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final synchronized void shutdown() {
|
public final synchronized void shutdown() {
|
||||||
@@ -199,7 +200,7 @@ public final class Channel {
|
|||||||
disconnectAwayPlayers();
|
disconnectAwayPlayers();
|
||||||
players.disconnectAll();
|
players.disconnectAll();
|
||||||
|
|
||||||
eventSM.cancel();
|
eventSM.dispose();
|
||||||
eventSM = null;
|
eventSM = null;
|
||||||
|
|
||||||
mapManager.dispose();
|
mapManager.dispose();
|
||||||
@@ -277,7 +278,7 @@ public final class Channel {
|
|||||||
return mapManager;
|
return mapManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseService getServiceAccess(ServiceType sv) {
|
public BaseService getServiceAccess(ChannelServices sv) {
|
||||||
return services.getAccess(sv).getService();
|
return services.getAccess(sv).getService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ public final class NPCAnimationHandler extends AbstractMaplePacketHandler {
|
|||||||
if (length == 6) { // NPC Talk
|
if (length == 6) { // NPC Talk
|
||||||
mplew.writeShort(SendOpcode.NPC_ACTION.getValue());
|
mplew.writeShort(SendOpcode.NPC_ACTION.getValue());
|
||||||
mplew.writeInt(slea.readInt());
|
mplew.writeInt(slea.readInt());
|
||||||
mplew.writeShort(slea.readShort());
|
mplew.write(slea.readByte()); // 2 bytes, thanks resinate
|
||||||
|
mplew.write(slea.readByte());
|
||||||
c.announce(mplew.getPacket());
|
c.announce(mplew.getPacket());
|
||||||
} else if (length > 6) { // NPC Move
|
} else if (length > 6) { // NPC Move
|
||||||
byte[] bytes = slea.read(length - 9);
|
byte[] bytes = slea.read(length - 9);
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ import client.inventory.MapleInventoryType;
|
|||||||
import client.inventory.MaplePet;
|
import client.inventory.MaplePet;
|
||||||
import constants.game.GameConstants;
|
import constants.game.GameConstants;
|
||||||
import constants.game.ScriptableNPCConstants;
|
import constants.game.ScriptableNPCConstants;
|
||||||
import constants.net.ServerConstants;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -116,16 +115,13 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Channel cserv = wserv.getChannel(c.getChannel());
|
Channel cserv = wserv.getChannel(c.getChannel());
|
||||||
if(cserv == null || !cserv.isActive()) {
|
if(cserv == null) {
|
||||||
c.setChannel(1);
|
c.setChannel(1);
|
||||||
cserv = wserv.getChannel(c.getChannel());
|
cserv = wserv.getChannel(c.getChannel());
|
||||||
|
|
||||||
if(cserv == null) {
|
if(cserv == null) {
|
||||||
c.disconnect(true, false);
|
c.disconnect(true, false);
|
||||||
return;
|
return;
|
||||||
} else if (!cserv.isActive()) {
|
|
||||||
c.announce(MaplePacketCreator.getAfterLoginError(7));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,13 +129,13 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
|||||||
boolean newcomer = false;
|
boolean newcomer = false;
|
||||||
|
|
||||||
IoSession session = c.getSession();
|
IoSession session = c.getSession();
|
||||||
String remoteHwid;
|
|
||||||
if (player == null) {
|
|
||||||
if (!server.validateCharacteridInTransition(session, cid)) {
|
if (!server.validateCharacteridInTransition(session, cid)) {
|
||||||
c.disconnect(true, false);
|
c.disconnect(true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String remoteHwid;
|
||||||
|
if (player == null) {
|
||||||
remoteHwid = MapleSessionCoordinator.getInstance().getGameSessionHwid(session);
|
remoteHwid = MapleSessionCoordinator.getInstance().getGameSessionHwid(session);
|
||||||
if (remoteHwid == null) {
|
if (remoteHwid == null) {
|
||||||
c.disconnect(true, false);
|
c.disconnect(true, false);
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
|||||||
map.broadcastMessage(chr, MaplePacketCreator.damageMonster(oid, bouncedamage), false, true);
|
map.broadcastMessage(chr, MaplePacketCreator.damageMonster(oid, bouncedamage), false, true);
|
||||||
attacker.aggroMonsterDamage(chr, bouncedamage);
|
attacker.aggroMonsterDamage(chr, bouncedamage);
|
||||||
}
|
}
|
||||||
MapleStatEffect bPressure = chr.getBuffEffect(MapleBuffStat.BODY_PRESSURE);
|
MapleStatEffect bPressure = chr.getBuffEffect(MapleBuffStat.BODY_PRESSURE); // thanks Atoot for noticing an issue on Body Pressure neutralise
|
||||||
if (bPressure != null) {
|
if (bPressure != null) {
|
||||||
Skill skill = SkillFactory.getSkill(Aran.BODY_PRESSURE);
|
Skill skill = SkillFactory.getSkill(Aran.BODY_PRESSURE);
|
||||||
if (!attacker.alreadyBuffedStats().contains(MonsterStatus.NEUTRALISE)) {
|
if (!attacker.alreadyBuffedStats().contains(MonsterStatus.NEUTRALISE)) {
|
||||||
|
|||||||
@@ -37,8 +37,12 @@ public class LoginStorage {
|
|||||||
private ConcurrentHashMap<Integer, List<Long>> loginHistory = new ConcurrentHashMap<>();
|
private ConcurrentHashMap<Integer, List<Long>> loginHistory = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public boolean registerLogin(int accountId) {
|
public boolean registerLogin(int accountId) {
|
||||||
List<Long> accHist = loginHistory.putIfAbsent(accountId, new LinkedList<Long>());
|
List<Long> accHist = loginHistory.get(accountId);
|
||||||
if (accHist != null) {
|
if (accHist == null) {
|
||||||
|
accHist = new LinkedList<Long>();
|
||||||
|
loginHistory.put(accountId, accHist);
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (accHist) {
|
synchronized (accHist) {
|
||||||
if (accHist.size() > YamlConfig.config.server.MAX_ACCOUNT_LOGIN_ATTEMPT) {
|
if (accHist.size() > YamlConfig.config.server.MAX_ACCOUNT_LOGIN_ATTEMPT) {
|
||||||
long blockExpiration = Server.getInstance().getCurrentTime() + YamlConfig.config.server.LOGIN_ATTEMPT_DURATION;
|
long blockExpiration = Server.getInstance().getCurrentTime() + YamlConfig.config.server.LOGIN_ATTEMPT_DURATION;
|
||||||
@@ -46,12 +50,7 @@ public class LoginStorage {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
accHist = loginHistory.get(accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (accHist) {
|
|
||||||
accHist.add(Server.getInstance().getCurrentTime() + YamlConfig.config.server.LOGIN_ATTEMPT_DURATION);
|
accHist.add(Server.getInstance().getCurrentTime() + YamlConfig.config.server.LOGIN_ATTEMPT_DURATION);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ import config.YamlConfig;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import net.server.world.MapleParty;
|
import net.server.world.MapleParty;
|
||||||
import net.server.coordinator.world.MapleInviteCoordinator.InviteType;
|
import net.server.coordinator.world.MapleInviteCoordinator.InviteType;
|
||||||
import net.server.coordinator.partysearch.PartySearchEchelon;
|
|
||||||
import net.server.coordinator.partysearch.PartySearchStorage;
|
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
|
|
||||||
@@ -38,11 +36,12 @@ import java.util.HashSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import net.server.coordinator.world.MapleInviteCoordinator;
|
import net.server.coordinator.world.MapleInviteCoordinator;
|
||||||
import provider.MapleData;
|
import provider.MapleData;
|
||||||
import provider.MapleDataProviderFactory;
|
import provider.MapleDataProviderFactory;
|
||||||
@@ -58,9 +57,9 @@ public class MaplePartySearchCoordinator {
|
|||||||
private Map<MapleJob, PartySearchEchelon> upcomers = new HashMap<>();
|
private Map<MapleJob, PartySearchEchelon> upcomers = new HashMap<>();
|
||||||
|
|
||||||
private List<MapleCharacter> leaderQueue = new LinkedList<>();
|
private List<MapleCharacter> leaderQueue = new LinkedList<>();
|
||||||
private final ReentrantReadWriteLock leaderQueueLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_QUEUE, true);
|
private final MonitoredReentrantReadWriteLock leaderQueueLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_QUEUE, true);
|
||||||
private final ReadLock leaderQueueRLock = leaderQueueLock.readLock();
|
private final MonitoredReadLock leaderQueueRLock = MonitoredReadLockFactory.createLock(leaderQueueLock);
|
||||||
private final WriteLock leaderQueueWLock = leaderQueueLock.writeLock();
|
private final MonitoredWriteLock leaderQueueWLock = MonitoredWriteLockFactory.createLock(leaderQueueLock);
|
||||||
|
|
||||||
private Map<Integer, MapleCharacter> searchLeaders = new HashMap<>();
|
private Map<Integer, MapleCharacter> searchLeaders = new HashMap<>();
|
||||||
private Map<Integer, LeaderSearchMetadata> searchSettings = new HashMap<>();
|
private Map<Integer, LeaderSearchMetadata> searchSettings = new HashMap<>();
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
@@ -40,9 +40,9 @@ import java.lang.ref.WeakReference;
|
|||||||
*/
|
*/
|
||||||
public class PartySearchEchelon {
|
public class PartySearchEchelon {
|
||||||
|
|
||||||
private final ReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_ECHELON, true);
|
private final MonitoredReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_ECHELON, true);
|
||||||
private final ReadLock psRLock = psLock.readLock();
|
private final MonitoredReadLock psRLock = MonitoredReadLockFactory.createLock(psLock);
|
||||||
private final WriteLock psWLock = psLock.writeLock();
|
private final MonitoredWriteLock psWLock = MonitoredWriteLockFactory.createLock(psLock);
|
||||||
|
|
||||||
private Map<Integer, WeakReference<MapleCharacter>> echelon = new HashMap<>(20);
|
private Map<Integer, WeakReference<MapleCharacter>> echelon = new HashMap<>(20);
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,14 @@ import java.util.Comparator;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
|
|
||||||
import tools.IntervalBuilder;
|
import tools.IntervalBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,9 +47,9 @@ public class PartySearchStorage {
|
|||||||
private List<PartySearchCharacter> storage = new ArrayList<>(20);
|
private List<PartySearchCharacter> storage = new ArrayList<>(20);
|
||||||
private IntervalBuilder emptyIntervals = new IntervalBuilder();
|
private IntervalBuilder emptyIntervals = new IntervalBuilder();
|
||||||
|
|
||||||
private final ReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_STORAGE, true);
|
private final MonitoredReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_STORAGE, true);
|
||||||
private final ReadLock psRLock = psLock.readLock();
|
private final MonitoredReadLock psRLock = MonitoredReadLockFactory.createLock(psLock);
|
||||||
private final WriteLock psWLock = psLock.writeLock();
|
private final MonitoredWriteLock psWLock = MonitoredWriteLockFactory.createLock(psLock);
|
||||||
|
|
||||||
public List<PartySearchCharacter> getStorageList() {
|
public List<PartySearchCharacter> getStorageList() {
|
||||||
psRLock.lock();
|
psRLock.lock();
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public final class CharlistRequestHandler extends AbstractMaplePacketHandler {
|
|||||||
|
|
||||||
int channel = slea.readByte() + 1;
|
int channel = slea.readByte() + 1;
|
||||||
Channel ch = wserv.getChannel(channel);
|
Channel ch = wserv.getChannel(channel);
|
||||||
if(ch == null || !ch.isActive()) {
|
if(ch == null) {
|
||||||
c.announce(MaplePacketCreator.getServerStatus(2));
|
c.announce(MaplePacketCreator.getServerStatus(2));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (c.finishLogin() == 0) {
|
if (c.finishLogin() == 0) {
|
||||||
|
c.checkChar(c.getAccID());
|
||||||
login(c);
|
login(c);
|
||||||
} else {
|
} else {
|
||||||
c.announce(MaplePacketCreator.getLoginFailed(7));
|
c.announce(MaplePacketCreator.getLoginFailed(7));
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services;
|
package net.server.services;
|
||||||
|
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services;
|
||||||
|
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
|
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services;
|
package net.server.services;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -17,9 +17,7 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services;
|
package net.server.services;
|
||||||
|
|
||||||
import net.server.channel.services.task.BaseService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
|
||||||
|
Copyleft (L) 2016 - 2019 RonanLana
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation version 3 as published by
|
||||||
|
the Free Software Foundation. You may not use, modify or distribute
|
||||||
|
this program under any other version of the GNU Affero General Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package net.server.services;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ronan
|
||||||
|
*/
|
||||||
|
public interface ServiceType <T extends Enum<?>> {
|
||||||
|
public abstract Service createService();
|
||||||
|
public int ordinal();
|
||||||
|
public T[] enumValues();
|
||||||
|
}
|
||||||
+6
-6
@@ -17,7 +17,7 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services;
|
package net.server.services;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -27,12 +27,12 @@ public class ServicesManager {
|
|||||||
|
|
||||||
private Service[] services;
|
private Service[] services;
|
||||||
|
|
||||||
public ServicesManager() {
|
public ServicesManager(ServiceType serviceBundle) {
|
||||||
ServiceType[] serviceTypes = ServiceType.values();
|
Enum[] serviceTypes = serviceBundle.enumValues();
|
||||||
|
|
||||||
services = new Service[serviceTypes.length];
|
services = new Service[serviceTypes.length];
|
||||||
for (ServiceType type : serviceTypes) {
|
for (Enum type : serviceTypes) {
|
||||||
services[type.ordinal()] = type.createService();
|
services[type.ordinal()] = ((ServiceType) type).createService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ public class ServicesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
for (int i = 0; i < ServiceType.values().length; i++) {
|
for (int i = 0; i < services.length; i++) {
|
||||||
services[i].dispose();
|
services[i].dispose();
|
||||||
}
|
}
|
||||||
services = null;
|
services = null;
|
||||||
+4
-2
@@ -17,11 +17,12 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services.task.channel;
|
||||||
|
|
||||||
|
import net.server.services.BaseService;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.channel.services.BaseScheduler;
|
import net.server.services.BaseScheduler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -37,6 +38,7 @@ public class EventService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
||||||
if(eventSchedulers[i] != null) {
|
if(eventSchedulers[i] != null) {
|
||||||
+4
-2
@@ -17,8 +17,9 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services.task.channel;
|
||||||
|
|
||||||
|
import net.server.services.BaseService;
|
||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -26,7 +27,7 @@ import net.server.audit.LockCollector;
|
|||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.audit.locks.MonitoredReentrantLock;
|
import net.server.audit.locks.MonitoredReentrantLock;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
import net.server.channel.services.BaseScheduler;
|
import net.server.services.BaseScheduler;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ public class FaceExpressionService extends BaseService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
||||||
if(faceExpressionSchedulers[i] != null) {
|
if(faceExpressionSchedulers[i] != null) {
|
||||||
+5
-3
@@ -17,8 +17,9 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services.task.channel;
|
||||||
|
|
||||||
|
import net.server.services.BaseService;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
|
||||||
@@ -28,8 +29,8 @@ import java.util.Set;
|
|||||||
import net.server.audit.LockCollector;
|
import net.server.audit.LockCollector;
|
||||||
import net.server.audit.locks.MonitoredReentrantLock;
|
import net.server.audit.locks.MonitoredReentrantLock;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
import net.server.channel.services.BaseScheduler;
|
import net.server.services.BaseScheduler;
|
||||||
import net.server.channel.services.SchedulerListener;
|
import net.server.services.SchedulerListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -45,6 +46,7 @@ public class MobAnimationService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
||||||
if(mobAnimationSchedulers[i] != null) {
|
if(mobAnimationSchedulers[i] != null) {
|
||||||
+4
-2
@@ -17,11 +17,12 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services.task.channel;
|
||||||
|
|
||||||
|
import net.server.services.BaseService;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.channel.services.BaseScheduler;
|
import net.server.services.BaseScheduler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -37,6 +38,7 @@ public class MobClearSkillService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
||||||
if(mobClearSkillSchedulers[i] != null) {
|
if(mobClearSkillSchedulers[i] != null) {
|
||||||
+4
-2
@@ -17,11 +17,12 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services.task.channel;
|
||||||
|
|
||||||
|
import net.server.services.BaseService;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.channel.services.BaseScheduler;
|
import net.server.services.BaseScheduler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -37,6 +38,7 @@ public class MobMistService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
||||||
if(mobMistSchedulers[i] != null) {
|
if(mobMistSchedulers[i] != null) {
|
||||||
+5
-3
@@ -17,8 +17,9 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services.task.channel;
|
||||||
|
|
||||||
|
import net.server.services.BaseService;
|
||||||
import client.status.MonsterStatusEffect;
|
import client.status.MonsterStatusEffect;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -29,8 +30,8 @@ import net.server.audit.LockCollector;
|
|||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.audit.locks.MonitoredReentrantLock;
|
import net.server.audit.locks.MonitoredReentrantLock;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
import net.server.channel.services.BaseScheduler;
|
import net.server.services.BaseScheduler;
|
||||||
import net.server.channel.services.SchedulerListener;
|
import net.server.services.SchedulerListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -46,6 +47,7 @@ public class MobStatusService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
||||||
if(mobStatusSchedulers[i] != null) {
|
if(mobStatusSchedulers[i] != null) {
|
||||||
+4
-2
@@ -17,11 +17,12 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services.task;
|
package net.server.services.task.channel;
|
||||||
|
|
||||||
|
import net.server.services.BaseService;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.channel.services.BaseScheduler;
|
import net.server.services.BaseScheduler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -37,6 +38,7 @@ public class OverallService extends BaseService { // thanks Alex for suggestin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
for(int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) {
|
||||||
if(channelSchedulers[i] != null) {
|
if(channelSchedulers[i] != null) {
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the HeavenMS MapleStory Server
|
||||||
|
Copyleft (L) 2016 - 2018 RonanLana
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
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 net.server.services.task.world;
|
||||||
|
|
||||||
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.services.BaseScheduler;
|
||||||
|
import net.server.services.BaseService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ronan
|
||||||
|
*/
|
||||||
|
public class CharacterSaveService extends BaseService {
|
||||||
|
|
||||||
|
CharacterSaveScheduler chrSaveScheduler = new CharacterSaveScheduler();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
if(chrSaveScheduler != null) {
|
||||||
|
chrSaveScheduler.dispose();
|
||||||
|
chrSaveScheduler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerSaveCharacter(int characterId, Runnable runAction) {
|
||||||
|
chrSaveScheduler.registerSaveCharacter(characterId, runAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CharacterSaveScheduler extends BaseScheduler {
|
||||||
|
|
||||||
|
public CharacterSaveScheduler() {
|
||||||
|
super(MonitoredLockType.WORLD_SAVECHARS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerSaveCharacter(Integer characterId, Runnable runAction) {
|
||||||
|
registerEntry(characterId, runAction, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregisterSaveCharacter(Integer characterId) {
|
||||||
|
interruptEntry(characterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
|
||||||
|
Copyleft (L) 2016 - 2019 RonanLana
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation version 3 as published by
|
||||||
|
the Free Software Foundation. You may not use, modify or distribute
|
||||||
|
this program under any other version of the GNU Affero General Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package net.server.services.type;
|
||||||
|
|
||||||
|
import net.server.services.ServiceType;
|
||||||
|
import net.server.services.task.channel.EventService;
|
||||||
|
import net.server.services.task.channel.FaceExpressionService;
|
||||||
|
import net.server.services.task.channel.MobAnimationService;
|
||||||
|
import net.server.services.task.channel.MobClearSkillService;
|
||||||
|
import net.server.services.task.channel.MobMistService;
|
||||||
|
import net.server.services.task.channel.MobStatusService;
|
||||||
|
import net.server.services.task.channel.OverallService;
|
||||||
|
import net.server.services.BaseService;
|
||||||
|
import net.server.services.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ronan
|
||||||
|
*/
|
||||||
|
public enum ChannelServices implements ServiceType {
|
||||||
|
|
||||||
|
MOB_STATUS(MobStatusService.class),
|
||||||
|
MOB_ANIMATION(MobAnimationService.class),
|
||||||
|
MOB_CLEAR_SKILL(MobClearSkillService.class),
|
||||||
|
MOB_MIST(MobMistService.class),
|
||||||
|
FACE_EXPRESSION(FaceExpressionService.class),
|
||||||
|
EVENT(EventService.class),
|
||||||
|
OVERALL(OverallService.class);
|
||||||
|
|
||||||
|
private Class<? extends BaseService> s;
|
||||||
|
|
||||||
|
private ChannelServices(Class<? extends BaseService> service) {
|
||||||
|
s = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Service createService() {
|
||||||
|
return new Service(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelServices[] enumValues() {
|
||||||
|
return ChannelServices.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+14
-11
@@ -17,32 +17,35 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package net.server.channel.services;
|
package net.server.services.type;
|
||||||
|
|
||||||
import net.server.channel.services.task.*;
|
import net.server.services.ServiceType;
|
||||||
|
import net.server.services.BaseService;
|
||||||
|
import net.server.services.Service;
|
||||||
|
import net.server.services.task.world.CharacterSaveService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Ronan
|
* @author Ronan
|
||||||
*/
|
*/
|
||||||
public enum ServiceType {
|
public enum WorldServices implements ServiceType {
|
||||||
|
|
||||||
MOB_STATUS(MobStatusService.class),
|
SAVE_CHARACTER(CharacterSaveService.class);
|
||||||
MOB_ANIMATION(MobAnimationService.class),
|
|
||||||
MOB_CLEAR_SKILL(MobClearSkillService.class),
|
|
||||||
MOB_MIST(MobMistService.class),
|
|
||||||
FACE_EXPRESSION(FaceExpressionService.class),
|
|
||||||
EVENT(EventService.class),
|
|
||||||
OVERALL(OverallService.class);
|
|
||||||
|
|
||||||
private Class<? extends BaseService> s;
|
private Class<? extends BaseService> s;
|
||||||
|
|
||||||
private ServiceType(Class<? extends BaseService> service) {
|
private WorldServices(Class<? extends BaseService> service) {
|
||||||
s = service;
|
s = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Service createService() {
|
public Service createService() {
|
||||||
return new Service(s);
|
return new Service(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldServices[] enumValues() {
|
||||||
|
return WorldServices.values();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,6 @@ import client.MapleCharacter;
|
|||||||
import client.MapleFamily;
|
import client.MapleFamily;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import constants.game.GameConstants;
|
import constants.game.GameConstants;
|
||||||
import constants.net.ServerConstants;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
@@ -50,9 +49,6 @@ import java.util.SortedMap;
|
|||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -74,9 +70,13 @@ import net.server.PlayerStorage;
|
|||||||
import net.server.Server;
|
import net.server.Server;
|
||||||
import net.server.audit.LockCollector;
|
import net.server.audit.LockCollector;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantLock;
|
import net.server.audit.locks.MonitoredReentrantLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import net.server.channel.Channel;
|
import net.server.channel.Channel;
|
||||||
import net.server.channel.CharacterIdChannelPair;
|
import net.server.channel.CharacterIdChannelPair;
|
||||||
import net.server.coordinator.world.MapleInviteCoordinator;
|
import net.server.coordinator.world.MapleInviteCoordinator;
|
||||||
@@ -87,6 +87,9 @@ import net.server.coordinator.partysearch.MaplePartySearchCoordinator;
|
|||||||
import net.server.guild.MapleGuild;
|
import net.server.guild.MapleGuild;
|
||||||
import net.server.guild.MapleGuildCharacter;
|
import net.server.guild.MapleGuildCharacter;
|
||||||
import net.server.guild.MapleGuildSummary;
|
import net.server.guild.MapleGuildSummary;
|
||||||
|
import net.server.services.BaseService;
|
||||||
|
import net.server.services.ServicesManager;
|
||||||
|
import net.server.services.type.WorldServices;
|
||||||
import net.server.task.CharacterAutosaverTask;
|
import net.server.task.CharacterAutosaverTask;
|
||||||
import net.server.task.FamilyDailyResetTask;
|
import net.server.task.FamilyDailyResetTask;
|
||||||
import net.server.task.FishingTask;
|
import net.server.task.FishingTask;
|
||||||
@@ -123,12 +126,13 @@ public class World {
|
|||||||
private Map<Integer, Pair<Integer, Integer>> relationshipCouples = new HashMap<>();
|
private Map<Integer, Pair<Integer, Integer>> relationshipCouples = new HashMap<>();
|
||||||
private Map<Integer, MapleGuildSummary> gsStore = new HashMap<>();
|
private Map<Integer, MapleGuildSummary> gsStore = new HashMap<>();
|
||||||
private PlayerStorage players = new PlayerStorage();
|
private PlayerStorage players = new PlayerStorage();
|
||||||
|
private ServicesManager services = new ServicesManager(WorldServices.SAVE_CHARACTER);
|
||||||
private MapleMatchCheckerCoordinator matchChecker = new MapleMatchCheckerCoordinator();
|
private MapleMatchCheckerCoordinator matchChecker = new MapleMatchCheckerCoordinator();
|
||||||
private MaplePartySearchCoordinator partySearch = new MaplePartySearchCoordinator();
|
private MaplePartySearchCoordinator partySearch = new MaplePartySearchCoordinator();
|
||||||
|
|
||||||
private final ReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true);
|
private final MonitoredReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true);
|
||||||
private ReadLock chnRLock = chnLock.readLock();
|
private MonitoredReadLock chnRLock = MonitoredReadLockFactory.createLock(chnLock);
|
||||||
private WriteLock chnWLock = chnLock.writeLock();
|
private MonitoredWriteLock chnWLock = MonitoredWriteLockFactory.createLock(chnLock);
|
||||||
|
|
||||||
private Map<Integer, SortedMap<Integer, MapleCharacter>> accountChars = new HashMap<>();
|
private Map<Integer, SortedMap<Integer, MapleCharacter>> accountChars = new HashMap<>();
|
||||||
private Map<Integer, MapleStorage> accountStorages = new HashMap<>();
|
private Map<Integer, MapleStorage> accountStorages = new HashMap<>();
|
||||||
@@ -145,9 +149,9 @@ public class World {
|
|||||||
|
|
||||||
private Map<Integer, Integer> owlSearched = new LinkedHashMap<>();
|
private Map<Integer, Integer> owlSearched = new LinkedHashMap<>();
|
||||||
private List<Map<Integer, Integer>> cashItemBought = new ArrayList<>(9);
|
private List<Map<Integer, Integer>> cashItemBought = new ArrayList<>(9);
|
||||||
private final ReentrantReadWriteLock suggestLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_SUGGEST, true);
|
private final MonitoredReentrantReadWriteLock suggestLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_SUGGEST, true);
|
||||||
private ReadLock suggestRLock = suggestLock.readLock();
|
private MonitoredReadLock suggestRLock = MonitoredReadLockFactory.createLock(suggestLock);
|
||||||
private WriteLock suggestWLock = suggestLock.writeLock();
|
private MonitoredWriteLock suggestWLock = MonitoredWriteLockFactory.createLock(suggestLock);
|
||||||
|
|
||||||
private Map<Integer, Integer> disabledServerMessages = new HashMap<>(); // reuse owl lock
|
private Map<Integer, Integer> disabledServerMessages = new HashMap<>(); // reuse owl lock
|
||||||
private MonitoredReentrantLock srvMessagesLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_SRVMESSAGES);
|
private MonitoredReentrantLock srvMessagesLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_SRVMESSAGES);
|
||||||
@@ -2064,6 +2068,14 @@ public class World {
|
|||||||
partySearch.runPartySearch();
|
partySearch.runPartySearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BaseService getServiceAccess(WorldServices sv) {
|
||||||
|
return services.getAccess(sv).getService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeWorldServices() {
|
||||||
|
services.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
private void clearWorldData() {
|
private void clearWorldData() {
|
||||||
List<MapleParty> pList;
|
List<MapleParty> pList;
|
||||||
partyLock.lock();
|
partyLock.lock();
|
||||||
@@ -2077,6 +2089,7 @@ public class World {
|
|||||||
p.disposeLocks();
|
p.disposeLocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeWorldServices();
|
||||||
disposeLocks();
|
disposeLocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import tools.MaplePacketCreator;
|
|||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import client.MapleCharacter.DelayedQuestUpdate;
|
import client.MapleCharacter.DelayedQuestUpdate;
|
||||||
import client.MapleClient;
|
import client.MapleClient;
|
||||||
|
import client.MapleJob;
|
||||||
import client.MapleQuestStatus;
|
import client.MapleQuestStatus;
|
||||||
import client.SkillFactory;
|
import client.SkillFactory;
|
||||||
import client.inventory.Equip;
|
import client.inventory.Equip;
|
||||||
@@ -94,6 +95,18 @@ public class AbstractPlayerInteraction {
|
|||||||
return c.getPlayer();
|
return c.getPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getJobId() {
|
||||||
|
return getPlayer().getJob().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapleJob getJob(){
|
||||||
|
return getPlayer().getJob();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return getPlayer().getLevel();
|
||||||
|
}
|
||||||
|
|
||||||
public MapleMap getMap() {
|
public MapleMap getMap() {
|
||||||
return c.getPlayer().getMap();
|
return c.getPlayer().getMap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,12 @@ import config.YamlConfig;
|
|||||||
import net.server.audit.LockCollector;
|
import net.server.audit.LockCollector;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.audit.locks.MonitoredReentrantLock;
|
import net.server.audit.locks.MonitoredReentrantLock;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import net.server.world.MapleParty;
|
import net.server.world.MapleParty;
|
||||||
import net.server.world.MaplePartyCharacter;
|
import net.server.world.MaplePartyCharacter;
|
||||||
import server.maps.MaplePortal;
|
import server.maps.MaplePortal;
|
||||||
@@ -55,9 +59,6 @@ import constants.inventory.ItemConstants;
|
|||||||
import constants.net.ServerConstants;
|
import constants.net.ServerConstants;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import net.server.coordinator.world.MapleEventRecallCoordinator;
|
import net.server.coordinator.world.MapleEventRecallCoordinator;
|
||||||
@@ -91,9 +92,9 @@ public class EventInstanceManager {
|
|||||||
private MapleExpedition expedition = null;
|
private MapleExpedition expedition = null;
|
||||||
private List<Integer> mapIds = new LinkedList<>();
|
private List<Integer> mapIds = new LinkedList<>();
|
||||||
|
|
||||||
private final ReentrantReadWriteLock lock = new MonitoredReentrantReadWriteLock(MonitoredLockType.EIM, true);
|
private final MonitoredReentrantReadWriteLock lock = new MonitoredReentrantReadWriteLock(MonitoredLockType.EIM, true);
|
||||||
private ReadLock rL = lock.readLock();
|
private MonitoredReadLock rL = MonitoredReadLockFactory.createLock(lock);
|
||||||
private WriteLock wL = lock.writeLock();
|
private MonitoredWriteLock wL = MonitoredWriteLockFactory.createLock(lock);
|
||||||
|
|
||||||
private MonitoredReentrantLock pL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_PARTY, true);
|
private MonitoredReentrantLock pL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_PARTY, true);
|
||||||
private MonitoredReentrantLock sL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_SCRIPT, true);
|
private MonitoredReentrantLock sL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_SCRIPT, true);
|
||||||
|
|||||||
@@ -21,9 +21,11 @@
|
|||||||
*/
|
*/
|
||||||
package scripting.event;
|
package scripting.event;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -48,7 +50,8 @@ public class EventScriptManager extends AbstractScriptManager {
|
|||||||
public EventManager em;
|
public EventManager em;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, EventEntry> events = new LinkedHashMap<>();
|
private static EventEntry fallback;
|
||||||
|
private Map<String, EventEntry> events = new ConcurrentHashMap<>();
|
||||||
private boolean active = false;
|
private boolean active = false;
|
||||||
|
|
||||||
public EventScriptManager(Channel cserv, String[] scripts) {
|
public EventScriptManager(Channel cserv, String[] scripts) {
|
||||||
@@ -59,12 +62,15 @@ public class EventScriptManager extends AbstractScriptManager {
|
|||||||
events.put(script, new EventEntry(iv, new EventManager(cserv, iv, script)));
|
events.put(script, new EventEntry(iv, new EventManager(cserv, iv, script)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
fallback = events.remove("0_EXAMPLE");
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventManager getEventManager(String event) {
|
public EventManager getEventManager(String event) {
|
||||||
EventEntry entry = events.get(event);
|
EventEntry entry = events.get(event);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
return null;
|
return fallback.em;
|
||||||
}
|
}
|
||||||
return entry.em;
|
return entry.em;
|
||||||
}
|
}
|
||||||
@@ -73,7 +79,7 @@ public class EventScriptManager extends AbstractScriptManager {
|
|||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
public final void init() {
|
||||||
for (EventEntry entry : events.values()) {
|
for (EventEntry entry : events.values()) {
|
||||||
try {
|
try {
|
||||||
entry.iv.put("em", entry.em);
|
entry.iv.put("em", entry.em);
|
||||||
@@ -84,16 +90,17 @@ public class EventScriptManager extends AbstractScriptManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
active = true;
|
active = events.size() > 1; // bootup loads only 1 script
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reloadScripts() {
|
private void reloadScripts() {
|
||||||
if (events.isEmpty()) {
|
Set<Entry<String, EventEntry>> eventEntries = new HashSet<>(events.entrySet());
|
||||||
|
if (eventEntries.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel cserv = events.values().iterator().next().em.getChannelServer();
|
Channel cserv = eventEntries.iterator().next().getValue().em.getChannelServer();
|
||||||
for (Entry<String, EventEntry> entry : events.entrySet()) {
|
for (Entry<String, EventEntry> entry : eventEntries) {
|
||||||
String script = entry.getKey();
|
String script = entry.getKey();
|
||||||
NashornScriptEngine iv = getScriptEngine("event/" + script + ".js");
|
NashornScriptEngine iv = getScriptEngine("event/" + script + ".js");
|
||||||
events.put(script, new EventEntry(iv, new EventManager(cserv, iv, script)));
|
events.put(script, new EventEntry(iv, new EventManager(cserv, iv, script)));
|
||||||
@@ -112,4 +119,18 @@ public class EventScriptManager extends AbstractScriptManager {
|
|||||||
entry.em.cancel();
|
entry.em.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
if (events.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<EventEntry> eventEntries = new HashSet<>(events.values());
|
||||||
|
events.clear();
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
for (EventEntry entry : eventEntries) {
|
||||||
|
entry.em.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,34 @@ public class MapScriptMethods extends AbstractPlayerInteraction {
|
|||||||
super(c);
|
super(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void displayCygnusIntro() {
|
||||||
|
switch (c.getPlayer().getMapId()) {
|
||||||
|
case 913040100:
|
||||||
|
lockUI();
|
||||||
|
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene0"));
|
||||||
|
break;
|
||||||
|
case 913040101:
|
||||||
|
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene1"));
|
||||||
|
break;
|
||||||
|
case 913040102:
|
||||||
|
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene2"));
|
||||||
|
break;
|
||||||
|
case 913040103:
|
||||||
|
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene3"));
|
||||||
|
break;
|
||||||
|
case 913040104:
|
||||||
|
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene4"));
|
||||||
|
break;
|
||||||
|
case 913040105:
|
||||||
|
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene5"));
|
||||||
|
break;
|
||||||
|
case 913040106:
|
||||||
|
lockUI();
|
||||||
|
c.announce(MaplePacketCreator.showIntro("Effect/Direction.img/cygnusJobTutorial/Scene6"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void displayAranIntro() {
|
public void displayAranIntro() {
|
||||||
switch (c.getPlayer().getMapId()) {
|
switch (c.getPlayer().getMapId()) {
|
||||||
case 914090010:
|
case 914090010:
|
||||||
|
|||||||
@@ -253,14 +253,6 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
return this.getText;
|
return this.getText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getJobId() {
|
|
||||||
return getPlayer().getJob().getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MapleJob getJob(){
|
|
||||||
return getPlayer().getJob();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean forceStartQuest(int id) {
|
public boolean forceStartQuest(int id) {
|
||||||
return forceStartQuest(id, npc);
|
return forceStartQuest(id, npc);
|
||||||
@@ -303,10 +295,6 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
getPlayer().gainExp(gain, true, true);
|
getPlayer().gainExp(gain, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLevel() {
|
|
||||||
return getPlayer().getLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showEffect(String effect) {
|
public void showEffect(String effect) {
|
||||||
getPlayer().getMap().broadcastMessage(MaplePacketCreator.environmentChange(effect, 3));
|
getPlayer().getMap().broadcastMessage(MaplePacketCreator.environmentChange(effect, 3));
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ 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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
@@ -60,7 +61,6 @@ import client.inventory.manipulator.MapleInventoryManipulator;
|
|||||||
import client.status.MonsterStatus;
|
import client.status.MonsterStatus;
|
||||||
import client.status.MonsterStatusEffect;
|
import client.status.MonsterStatusEffect;
|
||||||
import constants.inventory.ItemConstants;
|
import constants.inventory.ItemConstants;
|
||||||
import constants.net.ServerConstants;
|
|
||||||
import constants.skills.Aran;
|
import constants.skills.Aran;
|
||||||
import constants.skills.Assassin;
|
import constants.skills.Assassin;
|
||||||
import constants.skills.Bandit;
|
import constants.skills.Bandit;
|
||||||
@@ -1281,9 +1281,13 @@ public class MapleStatEffect {
|
|||||||
|
|
||||||
long leftDuration = (starttime + localDuration) - Server.getInstance().getCurrentTime();
|
long leftDuration = (starttime + localDuration) - Server.getInstance().getCurrentTime();
|
||||||
if (leftDuration > 0) {
|
if (leftDuration > 0) {
|
||||||
|
if (isDash() || isInfusion()) {
|
||||||
|
target.announce(MaplePacketCreator.givePirateBuff(activeStats, (skill ? sourceid : -sourceid), (int) leftDuration));
|
||||||
|
} else {
|
||||||
target.announce(MaplePacketCreator.giveBuff((skill ? sourceid : -sourceid), (int) leftDuration, activeStats));
|
target.announce(MaplePacketCreator.giveBuff((skill ? sourceid : -sourceid), (int) leftDuration, activeStats));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) {
|
private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) {
|
||||||
if (!isMonsterRiding() && !isCouponBuff() && !isMysticDoor() && !isHyperBody() && !isCombo()) { // last mystic door already dispelled if it has been used before.
|
if (!isMonsterRiding() && !isCouponBuff() && !isMysticDoor() && !isHyperBody() && !isCombo()) { // last mystic door already dispelled if it has been used before.
|
||||||
@@ -1398,7 +1402,6 @@ public class MapleStatEffect {
|
|||||||
//CancelEffectAction cancelAction = new CancelEffectAction(applyto, this, starttime);
|
//CancelEffectAction cancelAction = new CancelEffectAction(applyto, this, starttime);
|
||||||
//ScheduledFuture<?> schedule = TimerManager.getInstance().schedule(cancelAction, localDuration);
|
//ScheduledFuture<?> schedule = TimerManager.getInstance().schedule(cancelAction, localDuration);
|
||||||
applyto.registerEffect(this, starttime, starttime + localDuration, false);
|
applyto.registerEffect(this, starttime, starttime + localDuration, false);
|
||||||
|
|
||||||
if (mbuff != null) {
|
if (mbuff != null) {
|
||||||
applyto.getMap().broadcastMessage(applyto, mbuff, false);
|
applyto.getMap().broadcastMessage(applyto, mbuff, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import client.MapleClient;
|
|||||||
import client.inventory.Item;
|
import client.inventory.Item;
|
||||||
import client.inventory.ItemFactory;
|
import client.inventory.ItemFactory;
|
||||||
import client.inventory.MapleInventoryType;
|
import client.inventory.MapleInventoryType;
|
||||||
|
import constants.game.GameConstants;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
@@ -44,6 +45,7 @@ import tools.DatabaseConnection;
|
|||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import tools.FilePrinter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -67,51 +69,45 @@ public class MapleStorage {
|
|||||||
this.meso = meso;
|
this.meso = meso;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MapleStorage create(int id, int world) {
|
private static MapleStorage create(int id, int world) throws SQLException {
|
||||||
try {
|
|
||||||
Connection con = DatabaseConnection.getConnection();
|
Connection con = DatabaseConnection.getConnection();
|
||||||
try (PreparedStatement ps = con.prepareStatement("INSERT INTO storages (accountid, world, slots, meso) VALUES (?, ?, 4, 0)")) {
|
try (PreparedStatement ps = con.prepareStatement("INSERT INTO storages (accountid, world, slots, meso) VALUES (?, ?, 4, 0)")) {
|
||||||
ps.setInt(1, id);
|
ps.setInt(1, id);
|
||||||
ps.setInt(2, world);
|
ps.setInt(2, world);
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
con.close();
|
con.close();
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return loadOrCreateFromDB(id, world);
|
return loadOrCreateFromDB(id, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MapleStorage loadOrCreateFromDB(int id, int world) {
|
public static MapleStorage loadOrCreateFromDB(int id, int world) {
|
||||||
MapleStorage ret = null;
|
|
||||||
int storeId;
|
|
||||||
try {
|
try {
|
||||||
|
MapleStorage ret;
|
||||||
Connection con = DatabaseConnection.getConnection();
|
Connection con = DatabaseConnection.getConnection();
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT storageid, slots, meso FROM storages WHERE accountid = ? AND world = ?");
|
PreparedStatement ps = con.prepareStatement("SELECT storageid, slots, meso FROM storages WHERE accountid = ? AND world = ?");
|
||||||
ps.setInt(1, id);
|
ps.setInt(1, id);
|
||||||
ps.setInt(2, world);
|
ps.setInt(2, world);
|
||||||
|
|
||||||
ResultSet rs = ps.executeQuery();
|
ResultSet rs = ps.executeQuery();
|
||||||
if (!rs.next()) {
|
if (rs.next()) {
|
||||||
rs.close();
|
ret = new MapleStorage(rs.getInt("storageid"), (byte) rs.getInt("slots"), rs.getInt("meso"));
|
||||||
ps.close();
|
|
||||||
con.close();
|
|
||||||
return create(id, world);
|
|
||||||
} else {
|
|
||||||
storeId = rs.getInt("storageid");
|
|
||||||
ret = new MapleStorage(storeId, (byte) rs.getInt("slots"), rs.getInt("meso"));
|
|
||||||
rs.close();
|
|
||||||
ps.close();
|
|
||||||
for (Pair<Item, MapleInventoryType> item : ItemFactory.STORAGE.loadItems(ret.id, false)) {
|
for (Pair<Item, MapleInventoryType> item : ItemFactory.STORAGE.loadItems(ret.id, false)) {
|
||||||
ret.items.add(item.getLeft());
|
ret.items.add(item.getLeft());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ret = create(id, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
con.close();
|
con.close();
|
||||||
} catch (SQLException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
|
} catch (SQLException ex) { // exceptions leading to deploy null storages found thanks to Jefe
|
||||||
|
FilePrinter.printError(FilePrinter.STORAGE, ex, "SQL error occurred when trying to load storage for accountid " + id + ", world " + GameConstants.WORLD_NAMES[world]);
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getSlots() {
|
public byte getSlots() {
|
||||||
|
|||||||
@@ -102,18 +102,16 @@ public class MapleLifeFactory {
|
|||||||
MapleData monsterInfoData = monsterData.getChildByPath("info");
|
MapleData monsterInfoData = monsterData.getChildByPath("info");
|
||||||
|
|
||||||
List<MobAttackInfoHolder> attackInfos = new LinkedList<>();
|
List<MobAttackInfoHolder> attackInfos = new LinkedList<>();
|
||||||
MapleMonsterStats stats;
|
MapleMonsterStats stats = new MapleMonsterStats();
|
||||||
|
|
||||||
int linkMid = MapleDataTool.getIntConvert("link", monsterInfoData, 0);
|
int linkMid = MapleDataTool.getIntConvert("link", monsterInfoData, 0);
|
||||||
if (linkMid == 0) {
|
if (linkMid != 0) {
|
||||||
stats = new MapleMonsterStats();
|
|
||||||
} else {
|
|
||||||
Pair<MapleMonsterStats, List<MobAttackInfoHolder>> linkStats = getMonsterStats(linkMid);
|
Pair<MapleMonsterStats, List<MobAttackInfoHolder>> linkStats = getMonsterStats(linkMid);
|
||||||
if (linkStats == null) {
|
if (linkStats == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
stats = linkStats.getLeft();
|
// thanks resinate for noticing non-propagable infos such as revives getting retrieved
|
||||||
attackInfos.addAll(linkStats.getRight());
|
attackInfos.addAll(linkStats.getRight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,11 +72,11 @@ import tools.Randomizer;
|
|||||||
import net.server.audit.LockCollector;
|
import net.server.audit.LockCollector;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
import net.server.channel.services.ServiceType;
|
import net.server.services.type.ChannelServices;
|
||||||
import net.server.channel.services.task.MobAnimationService;
|
import net.server.services.task.channel.MobAnimationService;
|
||||||
import net.server.channel.services.task.MobClearSkillService;
|
import net.server.services.task.channel.MobClearSkillService;
|
||||||
import net.server.channel.services.task.MobStatusService;
|
import net.server.services.task.channel.MobStatusService;
|
||||||
import net.server.channel.services.task.OverallService;
|
import net.server.services.task.channel.OverallService;
|
||||||
import net.server.coordinator.world.MapleMonsterAggroCoordinator;
|
import net.server.coordinator.world.MapleMonsterAggroCoordinator;
|
||||||
import server.MapleStatEffect;
|
import server.MapleStatEffect;
|
||||||
import server.loot.MapleLootManager;
|
import server.loot.MapleLootManager;
|
||||||
@@ -338,7 +338,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(animationTime > 0) {
|
if(animationTime > 0) {
|
||||||
MobAnimationService service = (MobAnimationService) map.getChannelServer().getServiceAccess(ServiceType.MOB_ANIMATION);
|
MobAnimationService service = (MobAnimationService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_ANIMATION);
|
||||||
return service.registerMobOnAnimationEffect(map.getId(), this.hashCode(), animationTime);
|
return service.registerMobOnAnimationEffect(map.getId(), this.hashCode(), animationTime);
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
@@ -824,7 +824,6 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
|
|
||||||
if(htKilled) {
|
if(htKilled) {
|
||||||
reviveMap.killMonster(ht, killer, true);
|
reviveMap.killMonster(ht, killer, true);
|
||||||
ht.broadcastMobHpBar(killer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,18 +1040,22 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
return isBoss() && getTagColor() > 0;
|
return isBoss() && getTagColor() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void broadcastMonsterStatus() {
|
||||||
|
Collection<MonsterStatusEffect> mseList = this.getStati().values();
|
||||||
|
for (MapleCharacter chr : map.getAllPlayers()) {
|
||||||
|
announceMonsterStatusInternal(chr.getClient(), mseList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void announceMonsterStatus(MapleClient client) {
|
public void announceMonsterStatus(MapleClient client) {
|
||||||
statiLock.lock();
|
announceMonsterStatusInternal(client, this.getStati().values());
|
||||||
try {
|
}
|
||||||
if (stati.size() > 0) {
|
|
||||||
for (final MonsterStatusEffect mse : this.stati.values()) {
|
public void announceMonsterStatusInternal(MapleClient client, Collection<MonsterStatusEffect> mseList) {
|
||||||
|
for (MonsterStatusEffect mse : mseList) {
|
||||||
client.announce(MaplePacketCreator.applyMonsterStatus(getObjectId(), mse, null));
|
client.announce(MaplePacketCreator.applyMonsterStatus(getObjectId(), mse, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
statiLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSpawnData(MapleClient client) {
|
public void sendSpawnData(MapleClient client) {
|
||||||
@@ -1203,7 +1206,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
if (oldEffect != null) {
|
if (oldEffect != null) {
|
||||||
oldEffect.removeActiveStatus(stat);
|
oldEffect.removeActiveStatus(stat);
|
||||||
if (oldEffect.getStati().isEmpty()) {
|
if (oldEffect.getStati().isEmpty()) {
|
||||||
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ServiceType.MOB_STATUS);
|
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_STATUS);
|
||||||
service.interruptMobStatus(mapid, oldEffect);
|
service.interruptMobStatus(mapid, oldEffect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1310,7 +1313,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
statiLock.unlock();
|
statiLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ServiceType.MOB_STATUS);
|
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_STATUS);
|
||||||
service.registerMobStatus(mapid, status, cancelTask, duration + animationTime - 100, overtimeAction, overtimeDelay);
|
service.registerMobStatus(mapid, status, cancelTask, duration + animationTime - 100, overtimeAction, overtimeDelay);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1362,7 +1365,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
statiLock.unlock();
|
statiLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ServiceType.MOB_STATUS);
|
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_STATUS);
|
||||||
service.registerMobStatus(map.getId(), effect, cancelTask, duration);
|
service.registerMobStatus(map.getId(), effect, cancelTask, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1561,7 +1564,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MobClearSkillService service = (MobClearSkillService) map.getChannelServer().getServiceAccess(ServiceType.MOB_CLEAR_SKILL);
|
MobClearSkillService service = (MobClearSkillService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_CLEAR_SKILL);
|
||||||
service.registerMobClearSkillAction(mmap.getId(), r, cooltime);
|
service.registerMobClearSkillAction(mmap.getId(), r, cooltime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1630,7 +1633,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MobClearSkillService service = (MobClearSkillService) map.getChannelServer().getServiceAccess(ServiceType.MOB_CLEAR_SKILL);
|
MobClearSkillService service = (MobClearSkillService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_CLEAR_SKILL);
|
||||||
service.registerMobClearSkillAction(mmap.getId(), r, cooltime);
|
service.registerMobClearSkillAction(mmap.getId(), r, cooltime);
|
||||||
} finally {
|
} finally {
|
||||||
monsterLock.unlock();
|
monsterLock.unlock();
|
||||||
@@ -1678,7 +1681,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
public void run() {
|
public void run() {
|
||||||
int curHp = hp.get();
|
int curHp = hp.get();
|
||||||
if(curHp <= 1) {
|
if(curHp <= 1) {
|
||||||
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ServiceType.MOB_STATUS);
|
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_STATUS);
|
||||||
service.interruptMobStatus(map.getId(), status);
|
service.interruptMobStatus(map.getId(), status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1687,7 +1690,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
if (damage >= curHp) {
|
if (damage >= curHp) {
|
||||||
damage = curHp - 1;
|
damage = curHp - 1;
|
||||||
if (type == 1 || type == 2) {
|
if (type == 1 || type == 2) {
|
||||||
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ServiceType.MOB_STATUS);
|
MobStatusService service = (MobStatusService) map.getChannelServer().getServiceAccess(ChannelServices.MOB_STATUS);
|
||||||
service.interruptMobStatus(map.getId(), status);
|
service.interruptMobStatus(map.getId(), status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1744,7 +1747,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MobClearSkillService service = (MobClearSkillService) mmap.getChannelServer().getServiceAccess(ServiceType.MOB_CLEAR_SKILL);
|
MobClearSkillService service = (MobClearSkillService) mmap.getChannelServer().getServiceAccess(ChannelServices.MOB_CLEAR_SKILL);
|
||||||
service.registerMobClearSkillAction(mmap.getId(), r, milli);
|
service.registerMobClearSkillAction(mmap.getId(), r, milli);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1780,7 +1783,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
public Map<MonsterStatus, MonsterStatusEffect> getStati() {
|
public Map<MonsterStatus, MonsterStatusEffect> getStati() {
|
||||||
statiLock.lock();
|
statiLock.lock();
|
||||||
try {
|
try {
|
||||||
return Collections.unmodifiableMap(stati);
|
return new HashMap<>(stati);
|
||||||
} finally {
|
} finally {
|
||||||
statiLock.unlock();
|
statiLock.unlock();
|
||||||
}
|
}
|
||||||
@@ -2227,7 +2230,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// had to schedule this since mob wouldn't stick to puppet aggro who knows why
|
// had to schedule this since mob wouldn't stick to puppet aggro who knows why
|
||||||
OverallService service = (OverallService) this.getMap().getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) this.getMap().getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.registerOverallAction(this.getMap().getId(), r, YamlConfig.config.server.UPDATE_INTERVAL);
|
service.registerOverallAction(this.getMap().getId(), r, YamlConfig.config.server.UPDATE_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -361,12 +361,16 @@ public class MaplePlayerNPC extends AbstractMapleMapObject {
|
|||||||
int j = 0;
|
int j = 0;
|
||||||
for(int i = branchSid; i < nextBranchSid; i++) {
|
for(int i = branchSid; i < nextBranchSid; i++) {
|
||||||
if(!usedScriptIds.contains(i)) {
|
if(!usedScriptIds.contains(i)) {
|
||||||
|
if (MaplePlayerNPCFactory.isExistentScriptid(i)) { // thanks Ark, Zein, geno, Ariel, JrCl0wn for noticing client crashes due to use of missing scriptids
|
||||||
availables.add(i);
|
availables.add(i);
|
||||||
j++;
|
j++;
|
||||||
|
|
||||||
if(j == 20) {
|
if(j == 20) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
break; // after this point no more scriptids expected...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
package server.life;
|
package server.life;
|
||||||
|
|
||||||
|
import constants.net.ServerConstants;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -36,9 +37,15 @@ import provider.MapleDataTool;
|
|||||||
*/
|
*/
|
||||||
public class MaplePlayerNPCFactory {
|
public class MaplePlayerNPCFactory {
|
||||||
|
|
||||||
|
private static MapleDataProvider npcData = MapleDataProviderFactory.getDataProvider(new File("wz/Npc.wz"));
|
||||||
|
|
||||||
private static final Map<Integer, List<MaplePlayerNPC>> dnpcMaps = new HashMap<>();
|
private static final Map<Integer, List<MaplePlayerNPC>> dnpcMaps = new HashMap<>();
|
||||||
private static Integer runningDeveloperOid = 2147483000; // 647 slots, long enough
|
private static Integer runningDeveloperOid = 2147483000; // 647 slots, long enough
|
||||||
|
|
||||||
|
public static boolean isExistentScriptid(int scriptid) {
|
||||||
|
return npcData.getData(scriptid + ".img") != null;
|
||||||
|
}
|
||||||
|
|
||||||
public static void loadDeveloperRoomMetadata(MapleDataProvider npc) {
|
public static void loadDeveloperRoomMetadata(MapleDataProvider npc) {
|
||||||
MapleData thisData = npc.getData("9977777.img");
|
MapleData thisData = npc.getData("9977777.img");
|
||||||
if(thisData != null) {
|
if(thisData != null) {
|
||||||
@@ -60,7 +67,7 @@ public class MaplePlayerNPCFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void loadFactoryMetadata() {
|
public static void loadFactoryMetadata() {
|
||||||
MapleDataProvider npc = MapleDataProviderFactory.getDataProvider(new File("wz/Npc.wz"));
|
MapleDataProvider npc = npcData;
|
||||||
loadDeveloperRoomMetadata(npc);
|
loadDeveloperRoomMetadata(npc);
|
||||||
|
|
||||||
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
|
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ import client.status.MonsterStatus;
|
|||||||
import constants.game.GameConstants;
|
import constants.game.GameConstants;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import net.server.channel.services.ServiceType;
|
import net.server.services.type.ChannelServices;
|
||||||
import net.server.channel.services.task.OverallService;
|
import net.server.services.task.channel.OverallService;
|
||||||
import tools.Randomizer;
|
import tools.Randomizer;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapObject;
|
import server.maps.MapleMapObject;
|
||||||
@@ -117,7 +117,7 @@ public class MobSkill {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
OverallService service = (OverallService) monster.getMap().getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) monster.getMap().getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.registerOverallAction(monster.getMap().getId(), toRun, animationTime);
|
service.registerOverallAction(monster.getMap().getId(), toRun, animationTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,11 +27,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import provider.MapleData;
|
import provider.MapleData;
|
||||||
import provider.MapleDataProvider;
|
import provider.MapleDataProvider;
|
||||||
import provider.MapleDataProviderFactory;
|
import provider.MapleDataProviderFactory;
|
||||||
@@ -46,9 +47,9 @@ public class MobSkillFactory {
|
|||||||
private static Map<String, MobSkill> mobSkills = new HashMap<String, MobSkill>();
|
private static Map<String, MobSkill> mobSkills = new HashMap<String, MobSkill>();
|
||||||
private final static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Skill.wz"));
|
private final static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Skill.wz"));
|
||||||
private static MapleData skillRoot = dataSource.getData("MobSkill.img");
|
private static MapleData skillRoot = dataSource.getData("MobSkill.img");
|
||||||
private final static ReentrantReadWriteLock dataLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MOBSKILL_FACTORY);
|
private final static MonitoredReentrantReadWriteLock dataLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MOBSKILL_FACTORY);
|
||||||
private final static ReadLock rL = dataLock.readLock();
|
private final static MonitoredReadLock rL = MonitoredReadLockFactory.createLock(dataLock);
|
||||||
private final static WriteLock wL = dataLock.writeLock();
|
private final static MonitoredWriteLock wL = MonitoredWriteLockFactory.createLock(dataLock);
|
||||||
|
|
||||||
public static MobSkill getMobSkill(final int skillId, final int level) {
|
public static MobSkill getMobSkill(final int skillId, final int level) {
|
||||||
final String key = skillId + "" + level;
|
final String key = skillId + "" + level;
|
||||||
|
|||||||
@@ -56,14 +56,12 @@ public class MapleLootManager {
|
|||||||
qItemAmount = qCompleteAmount;
|
qItemAmount = qCompleteAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qItemAmount <= 0) {
|
// thanks kvmba for noticing quest items with no required amount failing to be detected as such
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int qItemStatus = chrInv.hasItem(dropEntry.itemId, qItemAmount);
|
int qItemStatus = chrInv.hasItem(dropEntry.itemId, qItemAmount);
|
||||||
if (qItemStatus == 2) {
|
if (qItemStatus == 2) {
|
||||||
continue;
|
continue;
|
||||||
} /*else if (restricted && qItemStatus == 1) {
|
} /*else if (restricted && qItemStatus == 1) { // one-of-a-kind loots should be available everytime, thanks onechord for noticing
|
||||||
continue;
|
continue;
|
||||||
}*/
|
}*/
|
||||||
} /*else if (restricted && chrInv.hasItem(dropEntry.itemId, 1) > 0) { // thanks Conrad, Legalize for noticing eligible loots not being available to drop for non-killer parties
|
} /*else if (restricted && chrInv.hasItem(dropEntry.itemId, 1) > 0) { // thanks Conrad, Legalize for noticing eligible loots not being available to drop for non-killer parties
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import config.YamlConfig;
|
|||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
|
|
||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import net.server.channel.services.ServiceType;
|
import net.server.services.type.ChannelServices;
|
||||||
import net.server.channel.services.task.OverallService;
|
import net.server.services.task.channel.OverallService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -133,7 +133,7 @@ public class MapleDoor {
|
|||||||
if (effectTimeLeft > 0) {
|
if (effectTimeLeft > 0) {
|
||||||
MapleMap town = destroyDoor.getTown();
|
MapleMap town = destroyDoor.getTown();
|
||||||
|
|
||||||
OverallService service = (OverallService) town.getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) town.getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.registerOverallAction(town.getId(), new Runnable() {
|
service.registerOverallAction(town.getId(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|||||||
@@ -20,11 +20,14 @@
|
|||||||
package server.maps;
|
package server.maps;
|
||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import client.MapleClient;
|
import client.MapleClient;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import net.server.world.MapleParty;
|
import net.server.world.MapleParty;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
|
|
||||||
@@ -41,9 +44,9 @@ public class MapleDoorObject extends AbstractMapleMapObject {
|
|||||||
private int linkedPortalId;
|
private int linkedPortalId;
|
||||||
private Point linkedPos;
|
private Point linkedPos;
|
||||||
|
|
||||||
private final ReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_DOOR, true);
|
private final MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_DOOR, true);
|
||||||
private ReentrantReadWriteLock.ReadLock rlock = locks.readLock();
|
private MonitoredReadLock rlock = MonitoredReadLockFactory.createLock(locks);
|
||||||
private ReentrantReadWriteLock.WriteLock wlock = locks.writeLock();
|
private MonitoredWriteLock wlock = MonitoredWriteLockFactory.createLock(locks);
|
||||||
|
|
||||||
public MapleDoorObject(int owner, MapleMap destination, MapleMap origin, int townPortalId, Point targetPosition, Point toPosition) {
|
public MapleDoorObject(int owner, MapleMap destination, MapleMap origin, int townPortalId, Point targetPosition, Point toPosition) {
|
||||||
super();
|
super();
|
||||||
|
|||||||
@@ -169,7 +169,8 @@ public class MapleFootholdTree {
|
|||||||
}
|
}
|
||||||
Collections.sort(xMatches);
|
Collections.sort(xMatches);
|
||||||
for (MapleFoothold fh : xMatches) {
|
for (MapleFoothold fh : xMatches) {
|
||||||
if (!fh.isWall() && fh.getY1() != fh.getY2()) {
|
if (!fh.isWall()) {
|
||||||
|
if (fh.getY1() != fh.getY2()) {
|
||||||
int calcY;
|
int calcY;
|
||||||
double s1 = Math.abs(fh.getY2() - fh.getY1());
|
double s1 = Math.abs(fh.getY2() - fh.getY1());
|
||||||
double s2 = Math.abs(fh.getX2() - fh.getX1());
|
double s2 = Math.abs(fh.getX2() - fh.getX1());
|
||||||
@@ -185,12 +186,13 @@ public class MapleFootholdTree {
|
|||||||
if (calcY >= p.y) {
|
if (calcY >= p.y) {
|
||||||
return fh;
|
return fh;
|
||||||
}
|
}
|
||||||
} else if (!fh.isWall()) {
|
} else {
|
||||||
if (fh.getY1() >= p.y) {
|
if (fh.getY1() >= p.y) {
|
||||||
return fh;
|
return fh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,20 +55,21 @@ import java.util.Random;
|
|||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import net.server.Server;
|
import net.server.Server;
|
||||||
import net.server.coordinator.world.MapleMonsterAggroCoordinator;
|
import net.server.coordinator.world.MapleMonsterAggroCoordinator;
|
||||||
import net.server.channel.Channel;
|
import net.server.channel.Channel;
|
||||||
import net.server.channel.services.ServiceType;
|
import net.server.services.type.ChannelServices;
|
||||||
import net.server.channel.services.task.FaceExpressionService;
|
import net.server.services.task.channel.FaceExpressionService;
|
||||||
import net.server.channel.services.task.MobMistService;
|
import net.server.services.task.channel.MobMistService;
|
||||||
import net.server.channel.services.task.OverallService;
|
import net.server.services.task.channel.OverallService;
|
||||||
import net.server.world.World;
|
import net.server.world.World;
|
||||||
import scripting.map.MapScriptManager;
|
import scripting.map.MapScriptManager;
|
||||||
import server.MapleItemInformationProvider;
|
import server.MapleItemInformationProvider;
|
||||||
@@ -177,10 +178,10 @@ public class MapleMap {
|
|||||||
private int timeExpand;
|
private int timeExpand;
|
||||||
|
|
||||||
//locks
|
//locks
|
||||||
private ReadLock chrRLock;
|
private MonitoredReadLock chrRLock;
|
||||||
private WriteLock chrWLock;
|
private MonitoredWriteLock chrWLock;
|
||||||
private ReadLock objectRLock;
|
private MonitoredReadLock objectRLock;
|
||||||
private WriteLock objectWLock;
|
private MonitoredWriteLock objectWLock;
|
||||||
|
|
||||||
private Lock lootLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_LOOT, true);
|
private Lock lootLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_LOOT, true);
|
||||||
|
|
||||||
@@ -196,13 +197,13 @@ public class MapleMap {
|
|||||||
if (this.monsterRate == 0) {
|
if (this.monsterRate == 0) {
|
||||||
this.monsterRate = 1;
|
this.monsterRate = 1;
|
||||||
}
|
}
|
||||||
final ReentrantReadWriteLock chrLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_CHRS, true);
|
final MonitoredReentrantReadWriteLock chrLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_CHRS, true);
|
||||||
chrRLock = chrLock.readLock();
|
chrRLock = MonitoredReadLockFactory.createLock(chrLock);
|
||||||
chrWLock = chrLock.writeLock();
|
chrWLock = MonitoredWriteLockFactory.createLock(chrLock);
|
||||||
|
|
||||||
final ReentrantReadWriteLock objectLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_OBJS, true);
|
final MonitoredReentrantReadWriteLock objectLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_OBJS, true);
|
||||||
objectRLock = objectLock.readLock();
|
objectRLock = MonitoredReadLockFactory.createLock(objectLock);
|
||||||
objectWLock = objectLock.writeLock();
|
objectWLock = MonitoredWriteLockFactory.createLock(objectLock);
|
||||||
|
|
||||||
aggroMonitor = new MapleMonsterAggroCoordinator();
|
aggroMonitor = new MapleMonsterAggroCoordinator();
|
||||||
}
|
}
|
||||||
@@ -570,7 +571,7 @@ public class MapleMap {
|
|||||||
initial.x = xLimits.right;
|
initial.x = xLimits.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point ret = calcPointBelow(new Point(initial.x, initial.y - 85));
|
Point ret = calcPointBelow(new Point(initial.x, initial.y - 85)); // actual drop ranges: default - 120, explosive - 360
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
ret = bsearchDropPos(initial, fallback);
|
ret = bsearchDropPos(initial, fallback);
|
||||||
}
|
}
|
||||||
@@ -758,6 +759,10 @@ public class MapleMap {
|
|||||||
final List<MonsterDropEntry> otherQuestEntry = new ArrayList<>();
|
final List<MonsterDropEntry> otherQuestEntry = new ArrayList<>();
|
||||||
sortDropEntries(YamlConfig.config.server.USE_SPAWN_RELEVANT_LOOT ? mob.retrieveRelevantDrops() : mi.retrieveEffectiveDrop(mob.getId()), dropEntry, visibleQuestEntry, otherQuestEntry, chr);
|
sortDropEntries(YamlConfig.config.server.USE_SPAWN_RELEVANT_LOOT ? mob.retrieveRelevantDrops() : mi.retrieveEffectiveDrop(mob.getId()), dropEntry, visibleQuestEntry, otherQuestEntry, chr);
|
||||||
|
|
||||||
|
if (dropEntry.isEmpty() && visibleQuestEntry.isEmpty()) { // thanks resinate
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
registerMobItemDrops(droptype, mobpos, chRate, pos, dropEntry, visibleQuestEntry, otherQuestEntry, globalEntry, chr, mob);
|
registerMobItemDrops(droptype, mobpos, chRate, pos, dropEntry, visibleQuestEntry, otherQuestEntry, globalEntry, chr, mob);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1333,6 +1338,18 @@ public class MapleMap {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int countBosses() {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for(MapleMonster mob: getAllMonsters()) {
|
||||||
|
if (mob.isBoss()) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean damageMonster(final MapleCharacter chr, final MapleMonster monster, final int damage) {
|
public boolean damageMonster(final MapleCharacter chr, final MapleMonster monster, final int damage) {
|
||||||
if (monster.getId() == 8800000) {
|
if (monster.getId() == 8800000) {
|
||||||
for (MapleMapObject object : chr.getMap().getMapObjects()) {
|
for (MapleMapObject object : chr.getMap().getMapObjects()) {
|
||||||
@@ -1388,6 +1405,9 @@ public class MapleMap {
|
|||||||
spawnedMonstersOnMap.decrementAndGet();
|
spawnedMonstersOnMap.decrementAndGet();
|
||||||
removeMapObject(monster);
|
removeMapObject(monster);
|
||||||
monster.disposeMapObject();
|
monster.disposeMapObject();
|
||||||
|
if (monster.hasBossHPBar()) { // thanks resinate for noticing boss HPbar not clearing after mob defeat in certain scenarios
|
||||||
|
broadcastBossHpMessage(monster, monster.hashCode(), monster.makeBossHPBarPacket(), monster.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1462,7 +1482,6 @@ public class MapleMap {
|
|||||||
if (mons != null) {
|
if (mons != null) {
|
||||||
if (mons.getId() == 8800000) {
|
if (mons.getId() == 8800000) {
|
||||||
makeMonsterReal(mons);
|
makeMonsterReal(mons);
|
||||||
mons.aggroUpdateController();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1904,10 +1923,7 @@ public class MapleMap {
|
|||||||
});
|
});
|
||||||
|
|
||||||
monster.aggroUpdateController();
|
monster.aggroUpdateController();
|
||||||
|
updateBossSpawn(monster);
|
||||||
if (monster.hasBossHPBar()) {
|
|
||||||
broadcastBossHpMessage(monster, monster.hashCode(), monster.makeBossHPBarPacket(), monster.getPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
spawnedMonstersOnMap.incrementAndGet();
|
spawnedMonstersOnMap.incrementAndGet();
|
||||||
addSelfDestructive(monster);
|
addSelfDestructive(monster);
|
||||||
@@ -1946,7 +1962,7 @@ public class MapleMap {
|
|||||||
public void dismissRemoveAfter(final MapleMonster monster) {
|
public void dismissRemoveAfter(final MapleMonster monster) {
|
||||||
Runnable removeAfterAction = monster.popRemoveAfterAction();
|
Runnable removeAfterAction = monster.popRemoveAfterAction();
|
||||||
if (removeAfterAction != null) {
|
if (removeAfterAction != null) {
|
||||||
OverallService service = (OverallService) this.getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) this.getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.forceRunOverallAction(mapid, removeAfterAction);
|
service.forceRunOverallAction(mapid, removeAfterAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2009,6 +2025,7 @@ public class MapleMap {
|
|||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
monster.aggroUpdateController();
|
monster.aggroUpdateController();
|
||||||
|
updateBossSpawn(monster);
|
||||||
|
|
||||||
if ((monster.getTeam() == 1 || monster.getTeam() == 0) && (isCPQMap() || isCPQMap2())) {
|
if ((monster.getTeam() == 1 || monster.getTeam() == 0) && (isCPQMap() || isCPQMap2())) {
|
||||||
List<MCSkill> teamS = null;
|
List<MCSkill> teamS = null;
|
||||||
@@ -2026,10 +2043,6 @@ public class MapleMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monster.hasBossHPBar()) {
|
|
||||||
broadcastBossHpMessage(monster, monster.hashCode(), monster.makeBossHPBarPacket(), monster.getPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monster.getDropPeriodTime() > 0) { //9300102 - Watchhog, 9300061 - Moon Bunny (HPQ), 9300093 - Tylus
|
if (monster.getDropPeriodTime() > 0) { //9300102 - Watchhog, 9300061 - Moon Bunny (HPQ), 9300093 - Tylus
|
||||||
if (monster.getId() == 9300102) {
|
if (monster.getId() == 9300102) {
|
||||||
monsterItemDrop(monster, monster.getDropPeriodTime());
|
monsterItemDrop(monster, monster.getDropPeriodTime());
|
||||||
@@ -2078,10 +2091,7 @@ public class MapleMap {
|
|||||||
});
|
});
|
||||||
|
|
||||||
monster.aggroUpdateController();
|
monster.aggroUpdateController();
|
||||||
|
updateBossSpawn(monster);
|
||||||
if (monster.hasBossHPBar()) {
|
|
||||||
broadcastBossHpMessage(monster, monster.hashCode(), monster.makeBossHPBarPacket(), monster.getPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
spawnedMonstersOnMap.incrementAndGet();
|
spawnedMonstersOnMap.incrementAndGet();
|
||||||
addSelfDestructive(monster);
|
addSelfDestructive(monster);
|
||||||
@@ -2105,8 +2115,9 @@ public class MapleMap {
|
|||||||
public void makeMonsterReal(final MapleMonster monster) {
|
public void makeMonsterReal(final MapleMonster monster) {
|
||||||
monster.setFake(false);
|
monster.setFake(false);
|
||||||
broadcastMessage(MaplePacketCreator.makeMonsterReal(monster));
|
broadcastMessage(MaplePacketCreator.makeMonsterReal(monster));
|
||||||
|
monster.broadcastMonsterStatus();
|
||||||
monster.aggroUpdateController();
|
monster.aggroUpdateController();
|
||||||
|
updateBossSpawn(monster);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void spawnReactor(final MapleReactor reactor) {
|
public void spawnReactor(final MapleReactor reactor) {
|
||||||
@@ -2208,7 +2219,7 @@ public class MapleMap {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MobMistService service = (MobMistService) this.getChannelServer().getServiceAccess(ServiceType.MOB_MIST);
|
MobMistService service = (MobMistService) this.getChannelServer().getServiceAccess(ChannelServices.MOB_MIST);
|
||||||
service.registerMobMistCancelAction(mapid, mistSchedule, duration);
|
service.registerMobMistCancelAction(mapid, mistSchedule, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2308,7 +2319,7 @@ public class MapleMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void registerMapSchedule(Runnable r, long delay) {
|
private void registerMapSchedule(Runnable r, long delay) {
|
||||||
OverallService service = (OverallService) this.getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) this.getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.registerOverallAction(mapid, r, delay);
|
service.registerOverallAction(mapid, r, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2795,7 +2806,7 @@ public class MapleMap {
|
|||||||
public void removePlayer(MapleCharacter chr) {
|
public void removePlayer(MapleCharacter chr) {
|
||||||
Channel cserv = chr.getClient().getChannelServer();
|
Channel cserv = chr.getClient().getChannelServer();
|
||||||
|
|
||||||
FaceExpressionService service = (FaceExpressionService) this.getChannelServer().getServiceAccess(ServiceType.FACE_EXPRESSION);
|
FaceExpressionService service = (FaceExpressionService) this.getChannelServer().getServiceAccess(ChannelServices.FACE_EXPRESSION);
|
||||||
service.unregisterFaceExpression(mapid, chr);
|
service.unregisterFaceExpression(mapid, chr);
|
||||||
chr.unregisterChairBuff();
|
chr.unregisterChairBuff();
|
||||||
|
|
||||||
@@ -2914,6 +2925,21 @@ public class MapleMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateBossSpawn(MapleMonster monster) {
|
||||||
|
if (monster.hasBossHPBar()) {
|
||||||
|
broadcastBossHpMessage(monster, monster.hashCode(), monster.makeBossHPBarPacket(), monster.getPosition());
|
||||||
|
}
|
||||||
|
if (monster.isBoss()) {
|
||||||
|
if (unclaimOwnership() != null) {
|
||||||
|
String mobName = MapleMonsterInformationProvider.getInstance().getMobNameFromId(monster.getId());
|
||||||
|
if (mobName != null) {
|
||||||
|
mobName = mobName.trim();
|
||||||
|
this.dropMessage(5, "This lawn has been taken siege by " + mobName + "'s forces and will be kept hold until their defeat.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void broadcastBossHpMessage(MapleMonster mm, int bossHash, final byte[] packet) {
|
public void broadcastBossHpMessage(MapleMonster mm, int bossHash, final byte[] packet) {
|
||||||
broadcastBossHpMessage(mm, bossHash, null, packet, Double.POSITIVE_INFINITY, null);
|
broadcastBossHpMessage(mm, bossHash, null, packet, Double.POSITIVE_INFINITY, null);
|
||||||
}
|
}
|
||||||
@@ -3556,7 +3582,7 @@ public class MapleMap {
|
|||||||
if (reactor.getDelay() > 0) {
|
if (reactor.getDelay() > 0) {
|
||||||
MapleMap reactorMap = reactor.getMap();
|
MapleMap reactorMap = reactor.getMap();
|
||||||
|
|
||||||
OverallService service = (OverallService) reactorMap.getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) reactorMap.getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.registerOverallAction(reactorMap.getId(), new Runnable() {
|
service.registerOverallAction(reactorMap.getId(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -4219,8 +4245,13 @@ public class MapleMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MapleCharacter unclaimOwnership() {
|
||||||
|
MapleCharacter lastOwner = this.mapOwner;
|
||||||
|
return unclaimOwnership(lastOwner) ? lastOwner : null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean unclaimOwnership(MapleCharacter chr) {
|
public boolean unclaimOwnership(MapleCharacter chr) {
|
||||||
if (mapOwner == chr) {
|
if (chr != null && mapOwner == chr) {
|
||||||
this.mapOwner = null;
|
this.mapOwner = null;
|
||||||
chr.setOwnedMap(null);
|
chr.setOwnedMap(null);
|
||||||
|
|
||||||
@@ -4255,7 +4286,7 @@ public class MapleMap {
|
|||||||
public void checkMapOwnerActivity() {
|
public void checkMapOwnerActivity() {
|
||||||
long timeNow = Server.getInstance().getCurrentTime();
|
long timeNow = Server.getInstance().getCurrentTime();
|
||||||
if (timeNow - mapOwnerLastActivityTime > 60000) {
|
if (timeNow - mapOwnerLastActivityTime > 60000) {
|
||||||
if (unclaimOwnership(mapOwner)) {
|
if (unclaimOwnership() != null) {
|
||||||
this.dropMessage(5, "This lawn is now free real estate.");
|
this.dropMessage(5, "This lawn is now free real estate.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -309,9 +309,10 @@ public class MapleMapFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
map.setMapName(MapleDataTool.getString("mapName", nameData.getChildByPath(getMapStringName(mapid)), ""));
|
map.setMapName(loadPlaceName(mapid));
|
||||||
map.setStreetName(MapleDataTool.getString("streetName", nameData.getChildByPath(getMapStringName(mapid)), ""));
|
map.setStreetName(loadStreetName(mapid));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (mapid / 1000 != 1020) { // explorer job introduction scenes
|
if (mapid / 1000 != 1020) { // explorer job introduction scenes
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -434,4 +435,20 @@ public class MapleMapFactory {
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String loadPlaceName(int mapid) throws Exception {
|
||||||
|
try {
|
||||||
|
return MapleDataTool.getString("mapName", nameData.getChildByPath(getMapStringName(mapid)), "");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String loadStreetName(int mapid) throws Exception {
|
||||||
|
try {
|
||||||
|
return MapleDataTool.getString("streetName", nameData.getChildByPath(getMapStringName(mapid)), "");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,12 @@ package server.maps;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
import scripting.event.EventInstanceManager;
|
import scripting.event.EventInstanceManager;
|
||||||
|
|
||||||
public class MapleMapManager {
|
public class MapleMapManager {
|
||||||
@@ -35,17 +36,17 @@ public class MapleMapManager {
|
|||||||
|
|
||||||
private Map<Integer, MapleMap> maps = new HashMap<>();
|
private Map<Integer, MapleMap> maps = new HashMap<>();
|
||||||
|
|
||||||
private ReadLock mapsRLock;
|
private MonitoredReadLock mapsRLock;
|
||||||
private WriteLock mapsWLock;
|
private MonitoredWriteLock mapsWLock;
|
||||||
|
|
||||||
public MapleMapManager(EventInstanceManager eim, int world, int channel) {
|
public MapleMapManager(EventInstanceManager eim, int world, int channel) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.event = eim;
|
this.event = eim;
|
||||||
|
|
||||||
ReentrantReadWriteLock rrwl = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_MANAGER);
|
MonitoredReentrantReadWriteLock rrwl = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_MANAGER);
|
||||||
this.mapsRLock = rrwl.readLock();
|
this.mapsRLock = MonitoredReadLockFactory.createLock(rrwl);
|
||||||
this.mapsWLock = rrwl.writeLock();
|
this.mapsWLock = MonitoredWriteLockFactory.createLock(rrwl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapleMap resetMap(int mapid) {
|
public MapleMap resetMap(int mapid) {
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ import server.TimerManager;
|
|||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.channel.services.ServiceType;
|
import net.server.services.type.ChannelServices;
|
||||||
import net.server.channel.services.task.OverallService;
|
import net.server.services.task.channel.OverallService;
|
||||||
import server.partyquest.GuardianSpawnPoint;
|
import server.partyquest.GuardianSpawnPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -371,7 +371,7 @@ public class MapleReactor extends AbstractMapleMapObject {
|
|||||||
|
|
||||||
delayedRespawnRun = r;
|
delayedRespawnRun = r;
|
||||||
|
|
||||||
OverallService service = (OverallService) map.getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) map.getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.registerOverallAction(map.getId(), r, this.getDelay());
|
service.registerOverallAction(map.getId(), r, this.getDelay());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +379,7 @@ public class MapleReactor extends AbstractMapleMapObject {
|
|||||||
Runnable r = delayedRespawnRun;
|
Runnable r = delayedRespawnRun;
|
||||||
|
|
||||||
if (r != null) {
|
if (r != null) {
|
||||||
OverallService service = (OverallService) map.getChannelServer().getServiceAccess(ServiceType.OVERALL);
|
OverallService service = (OverallService) map.getChannelServer().getServiceAccess(ChannelServices.OVERALL);
|
||||||
service.forceRunOverallAction(map.getId(), r);
|
service.forceRunOverallAction(map.getId(), r);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ public class MapleQuest {
|
|||||||
|
|
||||||
int ixSize = ix.size();
|
int ixSize = ix.size();
|
||||||
for (int i = 0; i < ixSize; i++) {
|
for (int i = 0; i < ixSize; i++) {
|
||||||
String progress = chr.getClient().getAbstractPlayerInteraction().getQuestProgress(infoNumber, i);
|
String progress = chr.getAbstractPlayerInteraction().getQuestProgress(infoNumber, i);
|
||||||
String ixProgress = ix.get(i);
|
String ixProgress = ix.get(i);
|
||||||
|
|
||||||
if (!progress.contentEquals(ixProgress)) {
|
if (!progress.contentEquals(ixProgress)) {
|
||||||
@@ -387,19 +387,19 @@ public class MapleQuest {
|
|||||||
public int getStartItemAmountNeeded(int itemid) {
|
public int getStartItemAmountNeeded(int itemid) {
|
||||||
MapleQuestRequirement req = startReqs.get(MapleQuestRequirementType.ITEM);
|
MapleQuestRequirement req = startReqs.get(MapleQuestRequirementType.ITEM);
|
||||||
if(req == null)
|
if(req == null)
|
||||||
return 0;
|
return Integer.MIN_VALUE;
|
||||||
|
|
||||||
ItemRequirement ireq = (ItemRequirement) req;
|
ItemRequirement ireq = (ItemRequirement) req;
|
||||||
return ireq.getItemAmountNeeded(itemid);
|
return ireq.getItemAmountNeeded(itemid, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCompleteItemAmountNeeded(int itemid) {
|
public int getCompleteItemAmountNeeded(int itemid) {
|
||||||
MapleQuestRequirement req = completeReqs.get(MapleQuestRequirementType.ITEM);
|
MapleQuestRequirement req = completeReqs.get(MapleQuestRequirementType.ITEM);
|
||||||
if(req == null)
|
if(req == null)
|
||||||
return 0;
|
return Integer.MAX_VALUE;
|
||||||
|
|
||||||
ItemRequirement ireq = (ItemRequirement) req;
|
ItemRequirement ireq = (ItemRequirement) req;
|
||||||
return ireq.getItemAmountNeeded(itemid);
|
return ireq.getItemAmountNeeded(itemid, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMobAmountNeeded(int mid) {
|
public int getMobAmountNeeded(int mid) {
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ public class ItemAction extends MapleQuestAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// thanks onechord for noticing quests unnecessarily giving out "full inventory" from quests that also takes items from players
|
// thanks onechord for noticing quests unnecessarily giving out "full inventory" from quests that also takes items from players
|
||||||
return chr.getClient().getAbstractPlayerInteraction().canHoldAllAfterRemoving(toAddItemids, toAddQuantity, toRemoveItemids, toRemoveQuantity);
|
return chr.getAbstractPlayerInteraction().canHoldAllAfterRemoving(toAddItemids, toAddQuantity, toRemoveItemids, toRemoveQuantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canGetItem(ItemData item, MapleCharacter chr) {
|
private boolean canGetItem(ItemData item, MapleCharacter chr) {
|
||||||
|
|||||||
@@ -96,11 +96,12 @@ public class ItemRequirement extends MapleQuestRequirement {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemAmountNeeded(int itemid) {
|
public int getItemAmountNeeded(int itemid, boolean complete) {
|
||||||
if(items.containsKey(itemid)) {
|
Integer amount = items.get(itemid);
|
||||||
return items.get(itemid);
|
if (amount != null) {
|
||||||
|
return amount;
|
||||||
|
} else {
|
||||||
|
return complete ? Integer.MAX_VALUE : Integer.MIN_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ package tools;
|
|||||||
import java.awt.geom.Line2D;
|
import java.awt.geom.Line2D;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
|
import net.server.audit.locks.MonitoredReadLock;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import net.server.audit.locks.MonitoredWriteLock;
|
||||||
|
import net.server.audit.locks.factory.MonitoredReadLockFactory;
|
||||||
|
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -36,13 +37,13 @@ public class IntervalBuilder {
|
|||||||
|
|
||||||
private List<Line2D> intervalLimits = new ArrayList<>();
|
private List<Line2D> intervalLimits = new ArrayList<>();
|
||||||
|
|
||||||
protected ReadLock intervalRlock;
|
protected MonitoredReadLock intervalRlock;
|
||||||
protected WriteLock intervalWlock;
|
protected MonitoredWriteLock intervalWlock;
|
||||||
|
|
||||||
public IntervalBuilder() {
|
public IntervalBuilder() {
|
||||||
ReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.INTERVAL, true);
|
MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.INTERVAL, true);
|
||||||
intervalRlock = locks.readLock();
|
intervalRlock = MonitoredReadLockFactory.createLock(locks);
|
||||||
intervalWlock = locks.writeLock();
|
intervalWlock = MonitoredWriteLockFactory.createLock(locks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refitOverlappedIntervals(int st, int en, int newFrom, int newTo) {
|
private void refitOverlappedIntervals(int st, int en, int newFrom, int newTo) {
|
||||||
|
|||||||
@@ -1086,7 +1086,6 @@ public class MaplePacketCreator {
|
|||||||
mplew.writeShort(chr.getHp());
|
mplew.writeShort(chr.getHp());
|
||||||
mplew.writeBool(false);
|
mplew.writeBool(false);
|
||||||
mplew.writeLong(getTime(Server.getInstance().getCurrentTime()));
|
mplew.writeLong(getTime(Server.getInstance().getCurrentTime()));
|
||||||
mplew.skip(18);
|
|
||||||
return mplew.getPacket();
|
return mplew.getPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,7 +1102,6 @@ public class MaplePacketCreator {
|
|||||||
mplew.writeInt(spawnPosition.x); // spawn position placement thanks to Arnah (Vertisy)
|
mplew.writeInt(spawnPosition.x); // spawn position placement thanks to Arnah (Vertisy)
|
||||||
mplew.writeInt(spawnPosition.y);
|
mplew.writeInt(spawnPosition.y);
|
||||||
mplew.writeLong(getTime(Server.getInstance().getCurrentTime()));
|
mplew.writeLong(getTime(Server.getInstance().getCurrentTime()));
|
||||||
mplew.skip(18);
|
|
||||||
return mplew.getPacket();
|
return mplew.getPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user