Initial Repository Push

This commit is contained in:
2022-04-30 09:41:17 -04:00
parent d4eef9097a
commit bbfdde57a3
835 changed files with 168392 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,554 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.InterestManagement;
import engine.Enum.DispatchChannel;
import engine.Enum.GameObjectType;
import engine.ai.MobileFSM;
import engine.ai.MobileFSM.STATE;
import engine.gameManager.GroupManager;
import engine.gameManager.SessionManager;
import engine.job.JobScheduler;
import engine.jobs.RefreshGroupJob;
import engine.net.AbstractNetMsg;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.LoadCharacterMsg;
import engine.net.client.msg.LoadStructureMsg;
import engine.net.client.msg.MoveToPointMsg;
import engine.net.client.msg.UnloadObjectsMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.HashSet;
import static engine.math.FastMath.sqr;
public enum InterestManager implements Runnable {
INTERESTMANAGER;
private static long lastTime;
private static boolean keepGoing = true;
public void shutdown() {
this.keepGoing = false;
}
InterestManager() {
Logger.info(" Interest Management thread is running.");
}
@Override
public void run() {
beginLoadJob();
}
private void beginLoadJob() {
InterestManager.lastTime = System.currentTimeMillis();
while (InterestManager.keepGoing) {
try {
updateAllPlayers();
} catch (Exception e) {
Logger.error("InterestManager.BeginLoadJob:updateAllPlayers", e);
}
try {
Thread.sleep(advanceOneSecond());
} catch (Exception e) {
Logger.error("InterestManager.BeginLoadJob:advanceOneSecond", e);
}
}
}
private long advanceOneSecond() {
long curTime = System.currentTimeMillis();
long dur = 1000 + this.lastTime - curTime;
if (dur < 0) {
// Last update took more then one second, not good...
Logger.warn("LoadJob took more then one second to complete.");
this.lastTime = curTime + 100;
return 100;
}
this.lastTime += 1000;
return dur;
}
private void updateAllPlayers() {
// get all players
for (PlayerCharacter pc : SessionManager.getAllActivePlayerCharacters()) {
if (pc == null)
continue;
ClientConnection origin = pc.getClientConnection();
if (origin == null)
continue;
if (!pc.isEnteredWorld())
continue;
if (pc.getTeleportLock().readLock().tryLock()) {
try {
updateStaticList(pc, origin);
updateMobileList(pc, origin);
} catch (Exception e) {
Logger.error(e);
} finally {
pc.getTeleportLock().readLock().unlock();
}
}
}
}
private void updateStaticList(PlayerCharacter player, ClientConnection origin) {
// Only update if we've moved far enough to warrant it
float distanceSquared = player.getLoc().distanceSquared2D(player.getLastStaticLoc());
if (distanceSquared > sqr(25))
player.setLastStaticLoc(player.getLoc());
else
return;
// Get Statics in range
HashSet<AbstractWorldObject> toLoad = WorldGrid.getObjectsInRangePartial(player.getLoc(), MBServerStatics.STRUCTURE_LOAD_RANGE,
MBServerStatics.MASK_STATIC);
// get list of obects loaded that need removed
HashSet<AbstractWorldObject> loadedStaticObjects = player.getLoadedStaticObjects();
HashSet<AbstractWorldObject> toRemove = null;
toRemove = new HashSet<>(loadedStaticObjects);
toRemove.removeAll(toLoad);
// unload static objects now out of range
if (toRemove.size() > 0) {
UnloadObjectsMsg uom = new UnloadObjectsMsg();
for (AbstractWorldObject obj : toRemove) {
if (obj.getObjectType().equals(GameObjectType.Building))
InterestManager.HandleSpecialUnload((Building) obj, origin);
if (obj != null && !obj.equals(player))
uom.addObject(obj);
}
Dispatch dispatch = Dispatch.borrow(player, uom);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
}
loadedStaticObjects.removeAll(toRemove);
// remove any object to load that are already loaded
toLoad.removeAll(loadedStaticObjects);
LoadStructureMsg lsm = new LoadStructureMsg();
LoadCharacterMsg lcm = null;
ArrayList<LoadCharacterMsg> lcmList = new ArrayList<>();
for (AbstractWorldObject awo : toLoad) {
if (awo.getObjectType().equals(GameObjectType.Building))
lsm.addObject((Building) awo);
else if (awo.getObjectType().equals(GameObjectType.Corpse)) {
Corpse corpse = (Corpse) awo;
lcm = new LoadCharacterMsg(corpse, PlayerCharacter.hideNonAscii());
Dispatch dispatch = Dispatch.borrow(player, lcm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
} else if (awo.getObjectType().equals(GameObjectType.NPC)) {
NPC npc = (NPC) awo;
lcm = new LoadCharacterMsg(npc, PlayerCharacter.hideNonAscii());
lcmList.add(lcm);
}
}
if (lsm.getStructureList().size() > 0) {
Dispatch dispatch = Dispatch.borrow(player, lsm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
}
for (LoadCharacterMsg lc : lcmList) {
Dispatch dispatch = Dispatch.borrow(player, lc);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
}
loadedStaticObjects.addAll(toLoad);
}
private void updateMobileList(PlayerCharacter player, ClientConnection origin) {
if (player == null)
return;
// Get list of players in range
// TODO for now use a generic getALL list, later tie into Quad Tree
HashSet<AbstractWorldObject> toLoad = WorldGrid.getObjectsInRangePartial(player.getLoc(), MBServerStatics.CHARACTER_LOAD_RANGE,
MBServerStatics.MASK_MOBILE);
HashSet<AbstractWorldObject> toRemove = new HashSet<>();
HashSet<AbstractWorldObject> toLoadToPlayer = new HashSet<>();
for (AbstractWorldObject loadedObject : toLoad) {
switch (loadedObject.getObjectType()) {
case PlayerCharacter:
PlayerCharacter loadedPlayer = (PlayerCharacter) loadedObject;
if (loadedPlayer.getObjectUUID() == player.getObjectUUID())
continue;
if (player.getSeeInvis() < loadedPlayer.getHidden())
continue;
if (loadedPlayer.safemodeInvis())
continue;
if (player.getLoadedObjects().contains(loadedPlayer))
continue;
if (!loadedPlayer.isInWorldGrid())
continue;
toLoadToPlayer.add(loadedPlayer);
break;
//not playerCharacter, mobs,npcs and corpses cant be invis or safemode, just add normaly
default:
if (player.getLoadedObjects().contains(loadedObject))
continue;
if (!loadedObject.isInWorldGrid())
continue;
toLoadToPlayer.add(loadedObject);
break;
}
}
float unloadDistance = MBServerStatics.CHARACTER_LOAD_RANGE;
for (AbstractWorldObject playerLoadedObject : player.getLoadedObjects()) {
if (playerLoadedObject.getObjectType().equals(GameObjectType.PlayerCharacter)) {
PlayerCharacter loadedPlayer = (PlayerCharacter) playerLoadedObject;
if (player.getSeeInvis() < loadedPlayer.getHidden())
toRemove.add(playerLoadedObject);
else if (loadedPlayer.safemodeInvis())
toRemove.add(playerLoadedObject);
}
if (!playerLoadedObject.isInWorldGrid())
toRemove.add(playerLoadedObject);
else if (playerLoadedObject.getLoc().distanceSquared2D(player.getLoc()) > unloadDistance * unloadDistance)
toRemove.add(playerLoadedObject);
}
player.getLoadedObjects().addAll(toLoadToPlayer);
player.getLoadedObjects().removeAll(toRemove);
// get list of obects loaded to remove
// unload objects now out of range
if (toRemove.size() > 0) {
UnloadObjectsMsg uom = new UnloadObjectsMsg();
for (AbstractWorldObject obj : toRemove) {
try {
if (obj != null)
if (obj.equals(player)) // don't unload self
continue;
uom.addObject(obj);
if (obj.getObjectType() == GameObjectType.Mob)
((Mob) obj).getPlayerAgroMap().remove(player.getObjectUUID());
} catch (Exception e) {
Logger.error("UnloadCharacter", obj.getObjectUUID() + " " + e.getMessage());
}
}
if (!uom.getObjectList().isEmpty()) {
Dispatch dispatch = Dispatch.borrow(player, uom);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
}
}
LoadCharacterMsg lcm = null;
ArrayList<AbstractWorldObject> players = new ArrayList<>();
ArrayList<AbstractWorldObject> addToList = new ArrayList<>();
for (AbstractWorldObject awo : toLoadToPlayer) {
// dont load yourself
try {
if (awo.equals(player))
continue;
if ((awo.getObjectTypeMask() & MBServerStatics.MASK_PLAYER) != 0) {
// object to load is a player
PlayerCharacter awopc = (PlayerCharacter) awo;
// dont load if invis
if (player.getSeeInvis() < awopc.getHidden())
continue;
lcm = new LoadCharacterMsg(awopc, PlayerCharacter.hideNonAscii());
players.add(awo);
// check if in a group with the person being loaded
// and if so set updateGroup flag
if (GroupManager.getGroup(player) != null
&& GroupManager.getGroup(player) == GroupManager.getGroup(awopc))
// submit a job as for some reason the client needs a delay
// with group updates
// as it wont update if we do RefreshGroup directly after
// sending the lcm below
JobScheduler.getInstance().scheduleJob(new RefreshGroupJob(player, awopc), MBServerStatics.LOAD_OBJECT_DELAY);
} else if ((awo.getObjectTypeMask() & MBServerStatics.MASK_MOB) != 0) {
Mob awonpc = (Mob) awo;
if (!awonpc.isAlive() && (awonpc.isPet() || awonpc.isSiege() || awonpc.isNecroPet() || awonpc.isPlayerGuard()))
continue;
if (awonpc.getState().equals(STATE.Respawn) || awonpc.getState().equals(STATE.Disabled))
continue;
awonpc.getPlayerAgroMap().put(player.getObjectUUID(), false);
MobileFSM.setAwake(awonpc, false);
// IVarController.setVariable(awonpc, "IntelligenceDisableDelay", (double) (System.currentTimeMillis() + 5000));
// awonpc.enableIntelligence();
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii());
} else if ((awo.getObjectTypeMask() & MBServerStatics.MASK_NPC) != 0) {
NPC awonpc = (NPC) awo;
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii());
} else if ((awo.getObjectTypeMask() & MBServerStatics.MASK_PET) != 0) {
Mob awonpc = (Mob) awo;
if (!awonpc.isAlive())
continue;
awonpc.getPlayerAgroMap().put(player.getObjectUUID(), false);
if (awonpc.isMob())
MobileFSM.setAwake(awonpc, false);
// IVarController.setVariable(awonpc, "IntelligenceDisableDelay", (double) (System.currentTimeMillis() + 5000));
// awonpc.enableIntelligence();
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii());
}
addToList.add(awo);
if (lcm != null) {
Dispatch dispatch = Dispatch.borrow(player, lcm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
}
} catch (Exception e) {
Logger.error(awo.getObjectUUID() + " " + e.getMessage());
}
//Delaying character loading to reduce bandwidth consumption
}
// send effects for all players being loaded
// do it on a timer otherwise we may get failures as te client needs
// time to process lcm
//Added effects to LoadCharacter Serialization.
//JobScheduler.getInstance().scheduleJob(new LoadEffectsJob(players, origin), MBServerStatics.LOAD_OBJECT_DELAY);
}
// Forces the loading of static objects (corpses and buildings).
// Needed to override threshold limits on loading statics
public static void forceLoad(AbstractWorldObject awo) {
AbstractNetMsg msg = null;
LoadStructureMsg lsm;
LoadCharacterMsg lcm;
NPC npc;
Corpse corpse;
HashSet<AbstractWorldObject> toUpdate;
switch (awo.getObjectType()) {
case Building:
lsm = new LoadStructureMsg();
lsm.addObject((Building) awo);
msg = lsm;
break;
case Corpse:
corpse = (Corpse) awo;
lcm = new LoadCharacterMsg(corpse, false);
msg = lcm;
break;
case NPC:
npc = (NPC) awo;
lcm = new LoadCharacterMsg(npc, false);
msg = lcm;
break;
default:
return;
}
toUpdate = WorldGrid.getObjectsInRangePartial(awo.getLoc(), MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER);
boolean send;
for (AbstractWorldObject tar : toUpdate) {
PlayerCharacter player = (PlayerCharacter) tar;
HashSet<AbstractWorldObject> loadedStaticObjects = player.getLoadedStaticObjects();
send = false;
if (!loadedStaticObjects.contains(awo)) {
loadedStaticObjects.add(awo);
send = true;
}
if (send) {
Dispatch dispatch = Dispatch.borrow(player, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
}
}
}
public static void HandleSpecialUnload(Building building, ClientConnection origin) {
if (Regions.FurnitureRegionMap.get(building.getObjectUUID()) == null)
return;
Regions buildingRegion = Regions.FurnitureRegionMap.get(building.getObjectUUID());
if (!buildingRegion.isOutside())
return;
MoveToPointMsg moveMsg = new MoveToPointMsg(building);
if (origin != null)
origin.sendMsg(moveMsg);
}
public synchronized void HandleLoadForEnterWorld(PlayerCharacter player) {
if (player == null)
return;
ClientConnection origin = player.getClientConnection();
if (origin == null)
return;
//Update static list
try {
updateStaticList(player, origin);
} catch (Exception e) {
Logger.error("InterestManager.updateAllStaticPlayers: " + player.getObjectUUID(), e);
}
//Update mobile list
try {
updateMobileList(player, origin);
} catch (Exception e) {
Logger.error("InterestManager.updateAllMobilePlayers: " + player.getObjectUUID(), e);
}
}
public synchronized void HandleLoadForTeleport(PlayerCharacter player) {
if (player == null)
return;
ClientConnection origin = player.getClientConnection();
if (origin == null)
return;
//Update static list
try {
updateStaticList(player, origin);
} catch (Exception e) {
Logger.error("InterestManager.updateAllStaticPlayers: " + player.getObjectUUID(), e);
}
//Update mobile list
try {
updateMobileList(player, origin);
} catch (Exception e) {
Logger.error("InterestManager.updateAllMobilePlayers: " + player.getObjectUUID(), e);
}
}
public static void reloadCharacter(AbstractCharacter absChar) {
UnloadObjectsMsg uom = new UnloadObjectsMsg();
uom.addObject(absChar);
LoadCharacterMsg lcm = new LoadCharacterMsg(absChar, false);
HashSet<AbstractWorldObject> toSend = WorldGrid.getObjectsInRangePartial(absChar.getLoc(), MBServerStatics.CHARACTER_LOAD_RANGE,
MBServerStatics.MASK_PLAYER);
PlayerCharacter pc = null;
if (absChar.getObjectType().equals(GameObjectType.PlayerCharacter))
pc = (PlayerCharacter) absChar;
for (AbstractWorldObject awo : toSend) {
PlayerCharacter pcc = (PlayerCharacter) awo;
if (pcc == null)
continue;
ClientConnection cc = SessionManager.getClientConnection(pcc);
if (cc == null)
continue;
if (pcc.getObjectUUID() == absChar.getObjectUUID())
continue;
else {
if (pc != null)
if (pcc.getSeeInvis() < pc.getHidden())
continue;
if (!cc.sendMsg(uom)) {
String classType = uom.getClass().getSimpleName();
Logger.error("Failed to send message ");
}
if (!cc.sendMsg(lcm)) {
String classType = lcm.getClass().getSimpleName();
Logger.error("Failed to send message");
}
}
}
}
}
+102
View File
@@ -0,0 +1,102 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.InterestManagement;
/* This class is the main interface for Magicbane's
* Interest management facilities.
*/
import engine.Enum;
import engine.math.Vector3fImmutable;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.msg.TerritoryChangeMessage;
import engine.objects.City;
import engine.objects.PlayerCharacter;
import engine.objects.Realm;
import engine.server.MBServerStatics;
import engine.util.MapLoader;
import org.pmw.tinylog.Logger;
import static engine.objects.Realm.getRealm;
public class RealmMap {
// Spatial hashmap. Used for detecting which Realm
// a player is currently in..
public static int[][] _realmImageMap;
public static int getRealmIDAtLocation(Vector3fImmutable pos) {
int xBuckets = (int) ((pos.getX() / MBServerStatics.MAX_WORLD_WIDTH) * MBServerStatics.SPATIAL_HASH_BUCKETSX);
int yBuckets = (int) ((pos.getZ() / MBServerStatics.MAX_WORLD_HEIGHT) * MBServerStatics.SPATIAL_HASH_BUCKETSY);
if (yBuckets < 0 || yBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSY
|| xBuckets < 0 || xBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSX) {
Logger.error("WorldServerRealm.getRealmFromPosition",
"Invalid range; Z: " + yBuckets + ", X: " + xBuckets);
return 255;
}
return RealmMap._realmImageMap[xBuckets][yBuckets];
}
public static Realm getRealmForCity(City city) {
Realm outRealm = null;
outRealm = city.getRealm();
return outRealm;
}
public static Realm getRealmAtLocation(Vector3fImmutable worldVector) {
return getRealm(RealmMap.getRealmIDAtLocation(worldVector));
}
public static void updateRealm(PlayerCharacter player){
int realmID = RealmMap.getRealmIDAtLocation(player.getLoc());
if (realmID != player.getLastRealmID()){
player.setLastRealmID(realmID);
Realm realm = Realm.getRealm(realmID);
if (realm != null){
if (realm.isRuled()){
City city = realm.getRulingCity();
if (city != null){
TerritoryChangeMessage tcm = new TerritoryChangeMessage((PlayerCharacter)realm.getRulingCity().getOwner(),realm);
Dispatch dispatch = Dispatch.borrow(player, tcm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
}else{
TerritoryChangeMessage tcm = new TerritoryChangeMessage(null,realm);
Dispatch dispatch = Dispatch.borrow(player, tcm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
}
}else{
TerritoryChangeMessage tcm = new TerritoryChangeMessage(null,realm);
Dispatch dispatch = Dispatch.borrow(player, tcm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
}
}
}
}
public static void loadRealmImageMap() {
RealmMap._realmImageMap = MapLoader.loadMap();
}
}
@@ -0,0 +1,312 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.InterestManagement;
import engine.Enum.GridObjectType;
import engine.math.FastMath;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.LoadCharacterMsg;
import engine.net.client.msg.LoadStructureMsg;
import engine.net.client.msg.UnloadObjectsMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
public class WorldGrid {
public static ConcurrentHashMap<Integer,AbstractWorldObject>[][] DynamicGridMap;
public static ConcurrentHashMap<Integer,AbstractWorldObject>[][] StaticGridMap;
private static float dynamicBucketScale = 0.00390625f; // 256 bucket size, 1/256
private static float staticBucketScale = 0.00390625f;
public static void startLoadJob() {
Thread loadJobThread;
loadJobThread = new Thread(InterestManager.INTERESTMANAGER);
loadJobThread.setName("InterestManager");
loadJobThread.start();
}
public static boolean moveWorldObject(AbstractWorldObject awo, Vector3fImmutable location) {
awo.setLoc(location);
return true;
}
public static HashSet<AbstractWorldObject> getInRange(Vector3f loc, double r) {
HashSet<AbstractWorldObject> outbound = new HashSet<>();
return outbound;
}
public static HashSet<AbstractWorldObject> getObjectsInRangePartial(Vector3fImmutable loc, double r, int mask) {
HashSet<AbstractWorldObject> outbound = new HashSet<>();
float scale;
if ((mask & MBServerStatics.MASK_STATIC) != 0)
scale = WorldGrid.staticBucketScale;
else
scale = WorldGrid.dynamicBucketScale;
int gridX = (int) Math.abs(loc.x * scale);
int gridZ = (int)Math.abs(loc.z * scale);
int bucketSize = (int) (r *scale) + 1;
//start at top left most corner to scan.
int startingX = gridX - bucketSize;
int startingZ = gridZ + bucketSize;
int limitX = Math.abs((int) (MBServerStatics.MAX_WORLD_WIDTH *scale));
int limitZ = Math.abs((int) (MBServerStatics.MAX_WORLD_HEIGHT *scale)); //LimitZ is negative, remember to flip sign.
if (startingX < 0)
startingX = 0;
if (startingZ < 0)
startingZ = 0;
if (startingX > limitX)
startingX = limitX;
if (startingZ > limitZ)
startingZ = limitZ;
int endX = startingX + (bucketSize * 2);
int endZ = startingZ - (bucketSize * 2);
if (endX < 0)
endX = 0;
if (endZ < 0)
endZ = 0;
if (endX > limitX)
endX = limitX;
if (endZ > limitZ)
endZ = limitZ;
int auditMob = 0;
for (int x = startingX;x<=endX;x++){
for (int z = startingZ;z >= endZ;z--){
ConcurrentHashMap<Integer,AbstractWorldObject> gridMap;
if ((MBServerStatics.MASK_STATIC & mask) != 0)
gridMap = WorldGrid.StaticGridMap[x][z];
else
gridMap = WorldGrid.DynamicGridMap[x][z];
for (AbstractWorldObject gridObject: gridMap.values()){
if ((gridObject.getObjectTypeMask() & mask) == 0)
continue;
if (gridObject.getLoc().distanceSquared2D(loc) <= FastMath.sqr(r))
outbound.add(gridObject);
}
}
}
return outbound;
}
public static HashSet<AbstractWorldObject> getObjectsInRangePartialNecroPets(Vector3fImmutable loc, double r) {
HashSet<AbstractWorldObject> outbound = new HashSet<>();
return outbound;
}
public static HashSet<AbstractWorldObject> getObjectsInRangeContains(Vector3fImmutable loc, double r, int mask) {
HashSet<AbstractWorldObject> outbound = getObjectsInRangePartial(loc,r,mask);
return outbound;
}
public static HashSet<AbstractWorldObject> getObjectsInRangePartial(AbstractWorldObject awo, double range, int mask) {
return getObjectsInRangePartial(awo.getLoc(), range, mask);
}
public static void InitializeGridObjects(){
int dynamicWidth = (int) Math.abs(MBServerStatics.MAX_WORLD_WIDTH *WorldGrid.dynamicBucketScale);
int dynamicHeight = (int) Math.abs(MBServerStatics.MAX_WORLD_HEIGHT*WorldGrid.dynamicBucketScale);
int staticWidth = (int) Math.abs(MBServerStatics.MAX_WORLD_WIDTH *WorldGrid.staticBucketScale);
int staticHeight = (int) Math.abs(MBServerStatics.MAX_WORLD_HEIGHT*WorldGrid.staticBucketScale);
WorldGrid.DynamicGridMap = new ConcurrentHashMap[dynamicWidth+ 1][dynamicHeight + 1];
WorldGrid.StaticGridMap = new ConcurrentHashMap[staticWidth + 1][staticHeight + 1];
//create new hash maps for each bucket
for (int x = 0; x<= staticWidth; x++)
for (int y = 0; y<= staticHeight; y++){
WorldGrid.StaticGridMap[x][y] = new ConcurrentHashMap<Integer,AbstractWorldObject>();
}
for (int x = 0; x<= dynamicWidth; x++)
for (int y = 0; y<= dynamicHeight; y++){
WorldGrid.DynamicGridMap[x][y] = new ConcurrentHashMap<Integer,AbstractWorldObject>();
}
}
public static void RemoveWorldObject(AbstractWorldObject gridObject){
if (gridObject == null)
return;
AbstractWorldObject.RemoveFromWorldGrid(gridObject);
}
public static boolean addObject(AbstractWorldObject gridObject, float x, float z){
if (gridObject == null)
return false;
if (x > MBServerStatics.MAX_WORLD_WIDTH)
return false;
if (z < MBServerStatics.MAX_WORLD_HEIGHT)
return false;
if (x < 0)
return false;
if (z > 0)
return false;
int gridX;
int gridZ;
if (gridObject.getGridObjectType().equals(GridObjectType.STATIC)){
gridX = Math.abs((int) (x *WorldGrid.staticBucketScale));
gridZ = Math.abs((int) (z*WorldGrid.staticBucketScale));
}else{
gridX = Math.abs((int) (x *WorldGrid.dynamicBucketScale));
gridZ = Math.abs((int) (z*WorldGrid.dynamicBucketScale));
}
WorldGrid.RemoveWorldObject(gridObject);
return AbstractWorldObject.AddToWorldGrid(gridObject, gridX, gridZ);
}
public static void unloadObject(AbstractWorldObject awo) {
UnloadObjectsMsg uom = new UnloadObjectsMsg();
uom.addObject(awo);
DispatchMessage.sendToAllInRange(awo, uom);
}
public static void loadObject(AbstractWorldObject awo) {
LoadStructureMsg lsm;
LoadCharacterMsg lcm;
switch (awo.getObjectType()) {
case Building:
lsm = new LoadStructureMsg();
lsm.addObject((Building)awo);
DispatchMessage.sendToAllInRange(awo, lsm);
break;
case NPC:
lcm = new LoadCharacterMsg((NPC) awo, false);
DispatchMessage.sendToAllInRange(awo, lcm);
break;
case Mob:
lcm = new LoadCharacterMsg((Mob) awo, false);
DispatchMessage.sendToAllInRange(awo, lcm);
break;
default:
// *** Refactor: Log error?
break;
}
}
public static void loadObject(AbstractWorldObject awo, ClientConnection origin) {
LoadStructureMsg lsm;
LoadCharacterMsg lcm;
switch (awo.getObjectType()) {
case Building:
lsm = new LoadStructureMsg();
lsm.addObject((Building)awo);
DispatchMessage.sendToAllInRange(awo, lsm);
break;
case NPC:
lcm = new LoadCharacterMsg((NPC) awo, false);
DispatchMessage.sendToAllInRange(awo, lcm);
break;
case Mob:
lcm = new LoadCharacterMsg((Mob) awo, false);
DispatchMessage.sendToAllInRange(awo, lcm);
break;
case PlayerCharacter:
lcm = new LoadCharacterMsg((PlayerCharacter) awo, false);
DispatchMessage.sendToAllInRange(awo, lcm);
break;
default:
// *** Refactor: Log error?
break;
}
}
public static void unloadObject(AbstractWorldObject awo,
ClientConnection origin) {
UnloadObjectsMsg uom = new UnloadObjectsMsg();
uom.addObject(awo);
DispatchMessage.sendToAllInRange(awo, uom);
}
public static void addObject(AbstractWorldObject awo, PlayerCharacter pc) {
if (pc == null || awo == null)
return;
ClientConnection origin = pc.getClientConnection();
if (origin == null)
return;
loadObject(awo, origin);
}
public static void removeObject(AbstractWorldObject awo, PlayerCharacter pc) {
if (pc == null || awo == null)
return;
ClientConnection origin = pc.getClientConnection();
if (origin == null)
return;
unloadObject(awo, origin);
}
public static void updateObject(AbstractWorldObject awo, PlayerCharacter pc) {
if (pc == null || awo == null)
return;
ClientConnection origin = pc.getClientConnection();
if (origin == null)
return;
unloadObject(awo, origin);
loadObject(awo, origin);
}
public static void updateObject(AbstractWorldObject awo) {
if (awo == null)
return;
unloadObject(awo);
loadObject(awo);
}
/*
*
*/
public static void removeObject(AbstractWorldObject awo) {
if (awo == null)
return;
unloadObject(awo);
}
}