Client clean-up + PiratePQ Implementation

Major update on client packets, now properly making unseen killed
monsters not appear as residual on a player's client. Many updates
revolving the PiratePQ environment as well.
This commit is contained in:
ronancpl
2017-04-12 15:32:55 -03:00
parent 768d9d0264
commit 6791a3d475
48 changed files with 990 additions and 194 deletions

View File

@@ -24,6 +24,7 @@ public class ServerConstants {
public static boolean JAVA_8;
public static boolean SHUTDOWNHOOK;
//Gameplay Configurations
public static final boolean USE_MAXRANGE = true; //will send and receive packets from all events of a map.
public static final boolean USE_DEBUG = true;
public static final boolean USE_MTS = false;
public static final boolean USE_FAMILY_SYSTEM = false;

View File

@@ -49,6 +49,7 @@ import server.life.MobAttackInfoFactory;
import server.life.MobSkill;
import server.life.MobSkillFactory;
import server.maps.MapleMap;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
@@ -69,42 +70,49 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
MapleMonster attacker = null;
final MapleMap map = player.getMap();
if (damagefrom != -3 && damagefrom != -4) {
monsteridfrom = slea.readInt();
oid = slea.readInt();
attacker = (MapleMonster) map.getMapObject(oid);
List<loseItem> loseItems;
if (attacker != null) {
if (attacker.isBuffed(MonsterStatus.NEUTRALISE)) {
return;
}
if (damage > 0) {
loseItems = map.getMonsterById(monsteridfrom).getStats().loseItem();
if (loseItems != null) {
MapleInventoryType type;
final int playerpos = player.getPosition().x;
byte d = 1;
Point pos = new Point(0, player.getPosition().y);
for (loseItem loseItem : loseItems) {
type = MapleItemInformationProvider.getInstance().getInventoryType(loseItem.getId());
for (byte b = 0; b < loseItem.getX(); b++) {//LOL?
if (Randomizer.nextInt(101) >= loseItem.getChance()) {
if (player.haveItem(loseItem.getId())) {
pos.x = (int) (playerpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
MapleInventoryManipulator.removeById(c, type, loseItem.getId(), 1, false, false);
map.spawnItemDrop(c.getPlayer(), c.getPlayer(), new Item(loseItem.getId(), (short) 0, (short) 1), map.calcDropPos(pos, player.getPosition()), true, true);
d++;
} else {
break;
monsteridfrom = slea.readInt();
oid = slea.readInt();
try {
attacker = (MapleMonster) map.getMapObject(oid);
List<loseItem> loseItems;
if (attacker != null) {
if (attacker.isBuffed(MonsterStatus.NEUTRALISE)) {
return;
}
if (damage > 0) {
loseItems = map.getMonsterById(monsteridfrom).getStats().loseItem();
if (loseItems != null) {
MapleInventoryType type;
final int playerpos = player.getPosition().x;
byte d = 1;
Point pos = new Point(0, player.getPosition().y);
for (loseItem loseItem : loseItems) {
type = MapleItemInformationProvider.getInstance().getInventoryType(loseItem.getId());
for (byte b = 0; b < loseItem.getX(); b++) {//LOL?
if (Randomizer.nextInt(101) >= loseItem.getChance()) {
if (player.haveItem(loseItem.getId())) {
pos.x = (int) (playerpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
MapleInventoryManipulator.removeById(c, type, loseItem.getId(), 1, false, false);
map.spawnItemDrop(c.getPlayer(), c.getPlayer(), new Item(loseItem.getId(), (short) 0, (short) 1), map.calcDropPos(pos, player.getPosition()), true, true);
d++;
} else {
break;
}
}
}
}
map.removeMapObject(attacker);
}
map.removeMapObject(attacker);
}
} else {
return;
}
} else {
return;
} catch(ClassCastException e) {
e.printStackTrace();
FilePrinter.print(FilePrinter.EXCEPTION_CAUGHT, "Attacker is not a mob-type, rather is a " + map.getMapObject(oid).getClass().getName() + " entity.");
}
direction = slea.readByte();
}
if (damagefrom != -1 && damagefrom != -2 && attacker != null) {

View File

@@ -87,6 +87,10 @@ public class AbstractPlayerInteraction {
public MapleCharacter getChar() {
return c.getPlayer();
}
public MapleMap getMap() {
return c.getPlayer().getMap();
}
public void warp(int map) {
getPlayer().changeMap(getWarpMap(map), getWarpMap(map).getPortal(0));
@@ -142,6 +146,14 @@ public class AbstractPlayerInteraction {
return getWarpMap(map);
}
public int countAllMonstersOnMap(int map) {
return getMap(map).countAllMonsters();
}
public int countMonster() {
return getPlayer().getMap().countAllMonsters();
}
public void resetMapObjects(int mapid) {
getWarpMap(mapid).resetMapObjects();
}
@@ -651,10 +663,6 @@ public class AbstractPlayerInteraction {
}
}
public void sendClock(MapleClient d, int time) {
d.announce(MaplePacketCreator.getClock((int) (time - System.currentTimeMillis()) / 1000));
}
public void useItem(int id) {
MapleItemInformationProvider.getInstance().getItemEffect(id).applyTo(c.getPlayer());
c.announce(MaplePacketCreator.getItemMessage(id));//Useful shet :3

View File

@@ -256,27 +256,27 @@ public class EventInstanceManager {
}
public void dispose() {
try {
em.getIv().invokeFunction("dispose", this);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
wL.lock();
try {
chars.clear();
} finally {
wL.unlock();
}
mobs.clear();
killCount.clear();
mapFactory = null;
if (expedition != null) {
em.getChannelServer().getExpeditions().remove(expedition);
}
em.disposeInstance(name);
em = null;
try {
em.getIv().invokeFunction("dispose", this);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
wL.lock();
try {
chars.clear();
} finally {
wL.unlock();
}
mobs.clear();
killCount.clear();
mapFactory = null;
if (expedition != null) {
em.getChannelServer().getExpeditions().remove(expedition);
}
em.disposeInstance(name);
em = null;
}
public MapleMapFactory getMapFactory() {

View File

@@ -38,6 +38,9 @@ import net.server.world.MapleParty;
import server.TimerManager;
import server.expeditions.MapleExpedition;
import server.maps.MapleMap;
import server.life.MapleMonster;
import server.life.MapleLifeFactory;
import client.MapleCharacter;
/**
@@ -194,4 +197,8 @@ public class EventManager {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public MapleMonster getMonster(int mid) {
return(MapleLifeFactory.getMonster(mid));
}
}

View File

@@ -82,7 +82,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
private int team;
private final HashMap<Integer, AtomicInteger> takenDamage = new HashMap<>();
public ReentrantLock monsterLock = new ReentrantLock();
private ReentrantLock monsterLock = new ReentrantLock();
public MapleMonster(int id, MapleMonsterStats stats) {
super(id);
@@ -93,6 +93,14 @@ public class MapleMonster extends AbstractLoadedMapleLife {
super(monster);
initWithStats(monster.stats);
}
public void lockMonster() {
monsterLock.lock();
}
public void unlockMonster() {
monsterLock.unlock();
}
private void initWithStats(MapleMonsterStats stats) {
setStance(5);
@@ -994,7 +1002,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
return(1.0f);
}
public final void changeLevelByDifficulty(final int difficulty, boolean pqMob) {
private final void changeLevelByDifficulty(final int difficulty, boolean pqMob) {
changeLevel((int)(this.getLevel() * getDifficultyRate(difficulty)), pqMob);
}

View File

@@ -32,6 +32,7 @@ import client.inventory.MaplePet;
import client.status.MonsterStatus;
import client.status.MonsterStatusEffect;
import constants.ItemConstants;
import constants.ServerConstants;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
@@ -181,6 +182,11 @@ public class MapleMap {
public void toggleDrops() {
this.dropsOn = !dropsOn;
}
private double getRangedDistance() {
return(ServerConstants.USE_MAXRANGE ? Double.POSITIVE_INFINITY : 722500);
}
public List<MapleMapObject> getMapObjectsInRect(Rectangle box, List<MapleMapObjectType> types) {
objectRLock.lock();
@@ -295,6 +301,25 @@ public class MapleMap {
objectWLock.unlock();
}
}
private void spawnRangedMapObject(MapleMapObject mapobject, DelayedPacketCreation packetbakery, SpawnCondition condition) {
chrRLock.lock();
try {
int curOID = getUsableOID();
mapobject.setObjectId(curOID);
for (MapleCharacter chr : characters) {
if (condition == null || condition.canSpawn(chr)) {
if (chr.getPosition().distanceSq(mapobject.getPosition()) <= 722500) {
packetbakery.sendPackets(chr.getClient());
chr.addVisibleMapObject(mapobject);
}
}
}
} finally {
chrRLock.unlock();
}
}
private int getUsableOID() {
if (runningOid.incrementAndGet() > 2000000000) {
@@ -485,6 +510,10 @@ public class MapleMap {
}
return count;
}
public int countAllMonsters() {
return getMapObjectsInRange(new Point(0, 0), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.MONSTER)).size();
}
public boolean damageMonster(final MapleCharacter chr, final MapleMonster monster, final int damage) {
if (monster.getId() == 8800000) {
@@ -499,7 +528,7 @@ public class MapleMap {
}
if (monster.isAlive()) {
boolean killed = false;
monster.monsterLock.lock();
monster.lockMonster();
try {
if (!monster.isAlive()) {
return false;
@@ -542,7 +571,7 @@ public class MapleMap {
}
}
} finally {
monster.monsterLock.unlock();
monster.unlockMonster();
}
if (monster.getStats().selfDestruction() != null && monster.getStats().selfDestruction().getHp() > -1) {// should work ;p
if (monster.getHp() <= monster.getStats().selfDestruction().getHp()) {
@@ -561,7 +590,7 @@ public class MapleMap {
public List<MapleMonster> getMonsters() {
List<MapleMonster> mobs = new ArrayList<MapleMonster>();
for (MapleMapObject object : this.getMapObjects()) {
mobs.add(this.getMonsterByOid(object.getObjectId()));
if(object instanceof MapleMonster) mobs.add((MapleMonster)object);
}
return mobs;
}
@@ -584,8 +613,10 @@ public class MapleMap {
if (chr == null) {
spawnedMonstersOnMap.decrementAndGet();
monster.setHp(0);
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
removeMapObject(monster);
monster.dispatchMonsterKilled();
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
//System.out.println("Counter: " + spawnedMonstersOnMap.toString() + " Size: " + countAllMonsters());
return;
}
if (monster.getStats().getLevel() >= chr.getLevel() + 30 && !chr.isGM()) {
@@ -619,7 +650,6 @@ public class MapleMap {
}
spawnedMonstersOnMap.decrementAndGet();
monster.setHp(0);
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
//if (monster.getStats().selfDestruction() == null) {//FUU BOMBS D:
removeMapObject(monster);
//}
@@ -663,6 +693,8 @@ public class MapleMap {
}
monster.dispatchMonsterKilled();
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
//System.out.println("Counter: " + spawnedMonstersOnMap.toString() + " Size: " + countAllMonsters());
}
public void killFriendlies(MapleMonster mob) {
@@ -834,7 +866,7 @@ public class MapleMap {
* @param monster
*/
public void updateMonsterController(MapleMonster monster) {
monster.monsterLock.lock();
monster.lockMonster();
try {
if (!monster.isAlive()) {
return;
@@ -869,7 +901,7 @@ public class MapleMap {
}
}
} finally {
monster.monsterLock.unlock();
monster.unlockMonster();
}
}
@@ -920,21 +952,12 @@ public class MapleMap {
*/
public MapleMonster getMonsterByOid(int oid) {
MapleMapObject mmo = getMapObject(oid);
if (mmo == null) {
return null;
}
if (mmo.getType() == MapleMapObjectType.MONSTER) {
return (MapleMonster) mmo;
}
return null;
return (mmo != null && mmo.getType() == MapleMapObjectType.MONSTER) ? (MapleMonster) mmo : null;
}
public MapleReactor getReactorByOid(int oid) {
MapleMapObject mmo = getMapObject(oid);
if (mmo == null) {
return null;
}
return mmo.getType() == MapleMapObjectType.REACTOR ? (MapleReactor) mmo : null;
return (mmo != null && mmo.getType() == MapleMapObjectType.REACTOR) ? (MapleReactor) mmo : null;
}
public MapleReactor getReactorByName(String name) {
@@ -1031,12 +1054,43 @@ public class MapleMap {
updateMonsterController(monster);
spawnedMonstersOnMap.incrementAndGet();
}
public void spawnAllMonsterIdFromMapSpawnList(int id) {
spawnAllMonsterIdFromMapSpawnList(id, 1, false);
}
public void spawnAllMonsterIdFromMapSpawnList(int id, int difficulty, boolean isPq) {
for(SpawnPoint sp: allMonsterSpawn) {
MapleMonster mm = sp.getMonster();
if(mm.getId() == id) {
spawnMonster(mm, difficulty, isPq);
}
}
}
public void spawnAllMonstersFromMapSpawnList() {
spawnAllMonstersFromMapSpawnList(1, false);
}
public void spawnAllMonstersFromMapSpawnList(int difficulty, boolean isPq) {
for(SpawnPoint sp: allMonsterSpawn) {
MapleMonster mm = sp.getMonster();
spawnMonster(mm, difficulty, isPq);
}
}
public void spawnMonster(final MapleMonster monster) {
spawnMonster(monster, 1, false);
}
public void spawnMonster(final MapleMonster monster, int difficulty, boolean isPq) {
if (mobCapacity != -1 && mobCapacity == spawnedMonstersOnMap.get()) {
System.out.println("got here");
return;//PyPQ
}
monster.changeDifficulty(difficulty, isPq);
monster.setMap(this);
if (!monster.getMap().getAllPlayer().isEmpty()) {
MapleCharacter chr = (MapleCharacter) getAllPlayer().get(0);
@@ -1051,6 +1105,7 @@ public class MapleMap {
c.announce(MaplePacketCreator.spawnMonster(monster, true));
}
}, null);
updateMonsterController(monster);
if (monster.getDropPeriodTime() > 0) { //9300102 - Watchhog, 9300061 - Moon Bunny (HPQ), 9300093 - Tylus
@@ -1433,6 +1488,7 @@ public class MapleMap {
}
sendObjectPlacement(chr.getClient());
if (isStartingEventMap() && !eventStarted()) {
chr.getMap().getPortal("join00").setPortalStatus(false);
}
@@ -1507,6 +1563,7 @@ public class MapleMap {
if(hasBoat() == 1) chr.getClient().announce((MaplePacketCreator.boatPacket(true)));
else chr.getClient().announce(MaplePacketCreator.boatPacket(false));
}
chr.receivePartyMemberHP();
}
@@ -1611,7 +1668,7 @@ public class MapleMap {
* @param rangedFrom
*/
public void broadcastMessage(final byte[] packet, Point rangedFrom) {
broadcastMessage(null, packet, 722500, rangedFrom);
broadcastMessage(null, packet, getRangedDistance(), rangedFrom);
}
/**
@@ -1622,7 +1679,7 @@ public class MapleMap {
* @param rangedFrom
*/
public void broadcastMessage(MapleCharacter source, final byte[] packet, Point rangedFrom) {
broadcastMessage(source, packet, 722500, rangedFrom);
broadcastMessage(source, packet, getRangedDistance(), rangedFrom);
}
private void broadcastMessage(MapleCharacter source, final byte[] packet, double rangeSq, Point rangedFrom) {
@@ -1687,7 +1744,7 @@ public class MapleMap {
objectRLock.unlock();
}
if (chr != null) {
for (MapleMapObject o : getMapObjectsInRange(chr.getPosition(), 722500, rangedMapobjectTypes)) {
for (MapleMapObject o : getMapObjectsInRange(chr.getPosition(), getRangedDistance(), rangedMapobjectTypes)) {
if (o.getType() == MapleMapObjectType.REACTOR) {
if (((MapleReactor) o).isAlive()) {
o.sendSpawnData(chr.getClient());
@@ -1865,7 +1922,7 @@ public class MapleMap {
objectRLock.unlock();
}
for (MapleMapObject mo : getMapObjectsInRange(player.getPosition(), 722500, rangedMapobjectTypes)) {
for (MapleMapObject mo : getMapObjectsInRange(player.getPosition(), getRangedDistance(), rangedMapobjectTypes)) {
if (!player.isMapObjectVisible(mo)) {
mo.sendSpawnData(player.getClient());
player.addVisibleMapObject(mo);
@@ -2055,8 +2112,6 @@ public class MapleMap {
for(SpawnPoint spawnPoint: allMonsterSpawn) {
if(spawnPoint.getMobTime() == -1) { //just those allowed to be spawned only once
MapleMonster monst = spawnPoint.getMonster();
monst.changeLevelByDifficulty(difficulty, isPq);
spawnMonster(monst);
}
}
@@ -2069,10 +2124,12 @@ public class MapleMap {
Collections.shuffle(randomSpawn);
int spawned = 0;
for (SpawnPoint spawnPoint : randomSpawn) {
spawnMonster(spawnPoint.getMonster());
spawned++;
if (spawned >= numShouldSpawn) {
break;
if(spawnPoint.shouldSpawn()) {
spawnMonster(spawnPoint.getMonster());
spawned++;
if (spawned >= numShouldSpawn) {
break;
}
}
}
}
@@ -2083,6 +2140,22 @@ public class MapleMap {
spawnPoint.setDenySpawn(false);
}
}
public void setAllowSpawnPointInBox(boolean allow, Rectangle box) {
for(SpawnPoint sp: monsterSpawn) {
if(box.contains(sp.getPosition())) {
sp.setDenySpawn(!allow);
}
}
}
public void setAllowSpawnPointInRange(boolean allow, Point from, double rangeSq) {
for(SpawnPoint sp: monsterSpawn) {
if(from.distanceSq(sp.getPosition()) <= rangeSq) {
sp.setDenySpawn(!allow);
}
}
}
public void respawn() {
chrRLock.lock();

View File

@@ -279,14 +279,20 @@ public class MapleMapFactory {
builder.append("victoria");
} else if (mapid >= 200000000 && mapid < 300000000) {
builder.append("ossyria");
} else if (mapid >= 300000000 && mapid < 400000000) {
builder.append("elin");
} else if (mapid >= 540000000 && mapid < 560000000) {
builder.append("singapore");
} else if (mapid >= 600000000 && mapid < 620000000) {
builder.append("MasteriaGL");
} else if (mapid >= 670000000 && mapid < 682000000) {
} else if (mapid >= 677000000 && mapid < 677100000) {
builder.append("Episode1GL");
} else if (mapid >= 670000000 && mapid < 690000000) {
builder.append("weddingGL");
} else if (mapid >= 682000000 && mapid < 683000000) {
builder.append("HalloweenGL");
} else if (mapid >= 683000000 && mapid < 684000000) {
builder.append("event");
} else if (mapid >= 800000000 && mapid < 900000000) {
builder.append("jp");
} else {

View File

@@ -127,11 +127,11 @@ public class MapleReactor extends AbstractMapleMapObject {
return MaplePacketCreator.spawnReactor(this);
}
public void forceHitReactor(final byte newState) {
setState((byte) newState);
setTimerActive(false);
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, (short) 0));
}
public void forceHitReactor(final byte newState) {
setState((byte) newState);
setTimerActive(false);
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, (short) 0));
}
public void delayedHitReactor(final MapleClient c, long delay) {
TimerManager.getInstance().schedule(new Runnable() {
@@ -147,49 +147,49 @@ public class MapleReactor extends AbstractMapleMapObject {
}
public synchronized void hitReactor(int charPos, short stance, int skillid, MapleClient c) {
try {
if(!this.isAlive()) {
return;
}
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "Hitted REACTOR " + this.getId() + " with POS " + charPos + " , STANCE " + stance + " , SkillID " + skillid);
if (stats.getType(state) < 999 && stats.getType(state) != -1) {//type 2 = only hit from right (kerning swamp plants), 00 is air left 02 is ground left
if (!(stats.getType(state) == 2 && (stance == 0 || stance == 2))) { //get next state
for (byte b = 0; b < stats.getStateSize(state); b++) {//YAY?
List<Integer> activeSkills = stats.getActiveSkills(state, b);
if (activeSkills != null) {
if (!activeSkills.contains(skillid)) continue;
}
state = stats.getNextState(state, b);
if (stats.getNextState(state, b) == -1) {//end of reactor
if (stats.getType(state) < 100) {//reactor broken
if (delay > 0) {
map.destroyReactor(getObjectId());
} else {//trigger as normal
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
} else {//item-triggered on final step
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "REACTOR " + this.getId() + " activated");
ReactorScriptManager.getInstance().act(c, this);
} else { //reactor not broken yet
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
if (state == stats.getNextState(state, b)) {//current state = next state, looping reactor
ReactorScriptManager.getInstance().act(c, this);
}
}
break;
}
}
} else {
state++;
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
ReactorScriptManager.getInstance().act(c, this);
}
} catch(Exception e) {
e.printStackTrace();
}
try {
if(!this.isAlive()) {
return;
}
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "Hitted REACTOR " + this.getId() + " with POS " + charPos + " , STANCE " + stance + " , SkillID " + skillid);
if (stats.getType(state) < 999 && stats.getType(state) != -1) {//type 2 = only hit from right (kerning swamp plants), 00 is air left 02 is ground left
if (!(stats.getType(state) == 2 && (stance == 0 || stance == 2))) { //get next state
for (byte b = 0; b < stats.getStateSize(state); b++) {//YAY?
List<Integer> activeSkills = stats.getActiveSkills(state, b);
if (activeSkills != null) {
if (!activeSkills.contains(skillid)) continue;
}
state = stats.getNextState(state, b);
if (stats.getNextState(state, b) == -1) {//end of reactor
if (stats.getType(state) < 100) {//reactor broken
if (delay > 0) {
map.destroyReactor(getObjectId());
} else {//trigger as normal
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
} else {//item-triggered on final step
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "REACTOR " + this.getId() + " activated");
ReactorScriptManager.getInstance().act(c, this);
} else { //reactor not broken yet
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
if (state == stats.getNextState(state, b)) {//current state = next state, looping reactor
ReactorScriptManager.getInstance().act(c, this);
}
}
break;
}
}
} else {
state++;
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
ReactorScriptManager.getInstance().act(c, this);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public Rectangle getArea() {