|
|
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
|
|
// Magicbane Emulator Project © 2013 - 2022
|
|
|
|
// www.magicbane.com
|
|
|
|
|
|
|
|
|
|
|
|
package engine.net.client.msg;
|
|
|
|
|
|
|
|
import engine.Enum;
|
|
|
|
import engine.gameManager.DbManager;
|
|
|
|
import engine.net.AbstractConnection;
|
|
|
|
import engine.net.ByteBufferReader;
|
|
|
|
import engine.net.ByteBufferWriter;
|
|
|
|
import engine.net.Network;
|
|
|
|
import engine.net.client.Protocol;
|
|
|
|
import engine.objects.AbstractGameObject;
|
|
|
|
import engine.objects.City;
|
|
|
|
import engine.objects.Mine;
|
|
|
|
import engine.objects.Runegate;
|
|
|
|
import engine.session.Session;
|
|
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
|
|
public class CityDataMsg extends ClientNetMsg {
|
|
|
|
|
|
|
|
public static final long wdComp = 0xFF00FF0000000003L;
|
|
|
|
private static final byte ver = 1;
|
|
|
|
private static ByteBuffer cachedEnterWorld;
|
|
|
|
private static long cachedExpireTime;
|
|
|
|
private final boolean forEnterWorld;
|
|
|
|
private Session s;
|
|
|
|
private boolean updateCities = false;
|
|
|
|
private boolean updateRunegates = false;
|
|
|
|
private boolean updateMines = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is the general purpose constructor.
|
|
|
|
*
|
|
|
|
* @param s Session
|
|
|
|
* @param forEnterWorld boolean flag
|
|
|
|
*/
|
|
|
|
public CityDataMsg(Session s, boolean forEnterWorld) {
|
|
|
|
super(Protocol.CITYDATA);
|
|
|
|
this.s = s;
|
|
|
|
this.forEnterWorld = forEnterWorld;
|
|
|
|
}
|
|
|
|
|
|
|
|
public CityDataMsg(boolean updateCities, boolean updateRunegates, boolean updateMines) {
|
|
|
|
super(Protocol.CITYDATA);
|
|
|
|
this.s = null;
|
|
|
|
this.forEnterWorld = false;
|
|
|
|
this.updateCities = updateCities;
|
|
|
|
this.updateRunegates = updateRunegates;
|
|
|
|
this.updateMines = updateMines;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This constructor is used by NetMsgFactory. It attempts to deserialize the
|
|
|
|
* ByteBuffer into a message. If a BufferUnderflow occurs (based on reading
|
|
|
|
* past the limit) then this constructor Throws that Exception to the
|
|
|
|
* caller.
|
|
|
|
*/
|
|
|
|
public CityDataMsg(AbstractConnection origin, ByteBufferReader reader) {
|
|
|
|
super(Protocol.CITYDATA, origin, reader);
|
|
|
|
this.forEnterWorld = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void attemptSerializeForEnterWorld(ByteBuffer bb) {
|
|
|
|
bb.clear();
|
|
|
|
ByteBufferWriter temp = new ByteBufferWriter(bb);
|
|
|
|
temp.put((byte) 0); // PAD
|
|
|
|
|
|
|
|
|
|
|
|
ArrayList<City> cityList = new ArrayList<>();
|
|
|
|
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
|
|
|
|
for (AbstractGameObject ago : map.values())
|
|
|
|
|
|
|
|
if (ago.getObjectType().equals(Enum.GameObjectType.City))
|
|
|
|
cityList.add((City) ago);
|
|
|
|
|
|
|
|
temp.putInt(cityList.size());
|
|
|
|
|
|
|
|
for (City city : cityList)
|
|
|
|
City.serializeForClientMsg(city, temp);
|
|
|
|
temp.put((byte) 0); // PAD
|
|
|
|
|
|
|
|
// Serialize runegates
|
|
|
|
|
|
|
|
temp.putInt(Runegate._runegates.values().size());
|
|
|
|
|
|
|
|
for (Runegate runegate : Runegate._runegates.values()) {
|
|
|
|
runegate._serializeForEnterWorld(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayList<Mine> mineList = new ArrayList<>();
|
|
|
|
for (Mine toAdd : Mine.mineMap.keySet()) {
|
|
|
|
mineList.add(toAdd);
|
|
|
|
}
|
|
|
|
|
|
|
|
temp.putInt(mineList.size());
|
|
|
|
for (Mine mine : mineList) {
|
|
|
|
if(mine.getParentZone() != null && !mine.getParentZone().isContinent())
|
|
|
|
Mine.serializeForClientMsg(mine, temp);
|
|
|
|
}
|
|
|
|
temp.put((byte) 0); // PAD
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected int getPowerOfTwoBufferSize() {
|
|
|
|
return (18); // 2^14 == 16384
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Serializes the subclass specific items to the supplied NetMsgWriter.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected void _serialize(ByteBufferWriter writer) {
|
|
|
|
if (this.forEnterWorld)
|
|
|
|
serializeForEnterWorld(writer);
|
|
|
|
else
|
|
|
|
serializeForMapUpdate(writer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Specific use serializer
|
|
|
|
*
|
|
|
|
* @param writer
|
|
|
|
*/
|
|
|
|
private void serializeForMapUpdate(ByteBufferWriter writer) {
|
|
|
|
|
|
|
|
//Handle City updates
|
|
|
|
|
|
|
|
if (this.updateCities) {
|
|
|
|
writer.put((byte) 0);
|
|
|
|
ArrayList<City> cityList = new ArrayList<>();
|
|
|
|
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
|
|
|
|
if (map != null) {
|
|
|
|
for (AbstractGameObject ago : map.values())
|
|
|
|
if (ago.getObjectType().equals(Enum.GameObjectType.City))
|
|
|
|
cityList.add((City) ago);
|
|
|
|
|
|
|
|
writer.putInt(cityList.size());
|
|
|
|
for (City city : cityList) {
|
|
|
|
City.serializeForClientMsg(city, writer);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
Logger.error("missing city map");
|
|
|
|
writer.putInt(0);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
writer.put((byte) 1);
|
|
|
|
|
|
|
|
|
|
|
|
//Handle Runegate updates
|
|
|
|
if (this.updateRunegates) {
|
|
|
|
|
|
|
|
writer.put((byte) 0);
|
|
|
|
writer.putInt(Runegate._runegates.values().size());
|
|
|
|
|
|
|
|
for (Runegate runegate : Runegate._runegates.values()) {
|
|
|
|
runegate._serializeForEnterWorld(writer);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
writer.put((byte) 1);
|
|
|
|
|
|
|
|
|
|
|
|
//Handle Mine updates
|
|
|
|
try {
|
|
|
|
if (this.updateMines) {
|
|
|
|
ArrayList<Mine> mineList = new ArrayList<>();
|
|
|
|
for (Mine toAdd : Mine.mineMap.keySet()) {
|
|
|
|
mineList.add(toAdd);
|
|
|
|
}
|
|
|
|
|
|
|
|
writer.putInt(mineList.size());
|
|
|
|
for (Mine mine : mineList) {
|
|
|
|
if(mine.getParentZone() != null && !mine.getParentZone().isContinent())
|
|
|
|
Mine.serializeForClientMsg(mine, writer);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
writer.putInt(0);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Logger.error(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
writer.put((byte) 0); // PAD
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Specific use serializer
|
|
|
|
*
|
|
|
|
* @param writer
|
|
|
|
*/
|
|
|
|
private void serializeForEnterWorld(ByteBufferWriter writer) {
|
|
|
|
if (s == null || s.getPlayerCharacter() == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
long startT = System.currentTimeMillis();
|
|
|
|
|
|
|
|
if (cachedEnterWorld == null) {
|
|
|
|
// Never before been cached, so init stuff
|
|
|
|
cachedEnterWorld = Network.byteBufferPool.getBuffer(19);
|
|
|
|
cachedExpireTime = 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check to see if its time to renew cache.
|
|
|
|
if (cachedExpireTime < System.currentTimeMillis()) {
|
|
|
|
synchronized (cachedEnterWorld) {
|
|
|
|
CityDataMsg.attemptSerializeForEnterWorld(cachedEnterWorld);
|
|
|
|
}
|
|
|
|
cachedExpireTime = startT + 60000;
|
|
|
|
}
|
|
|
|
|
|
|
|
writer.putBB(cachedEnterWorld);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deserializes the subclass specific items from the supplied NetMsgReader.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected void _deserialize(ByteBufferReader reader) {
|
|
|
|
// Client only sends 11 bytes.
|
|
|
|
|
|
|
|
byte type = reader.get();
|
|
|
|
|
|
|
|
if (type == 1) {
|
|
|
|
reader.get();
|
|
|
|
reader.get();
|
|
|
|
reader.getInt();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
reader.get();
|
|
|
|
reader.getInt();
|
|
|
|
reader.get();
|
|
|
|
reader.getInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the s
|
|
|
|
*/
|
|
|
|
public Session getS() {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the forEnterWorld
|
|
|
|
*/
|
|
|
|
public boolean isForEnterWorld() {
|
|
|
|
return forEnterWorld;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void updateCities(boolean value) {
|
|
|
|
this.updateCities = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void updateRunegates(boolean value) {
|
|
|
|
this.updateRunegates = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void updateMines(boolean value) {
|
|
|
|
this.updateMines = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|