forked from MagicBane/Server
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
9.9 KiB
317 lines
9.9 KiB
package engine.devcmd.cmds; |
|
|
|
import engine.Enum; |
|
import engine.Enum.BuildingGroup; |
|
import engine.Enum.GameObjectType; |
|
import engine.InterestManagement.WorldGrid; |
|
import engine.devcmd.AbstractDevCmd; |
|
import engine.gameManager.BuildingManager; |
|
import engine.gameManager.DbManager; |
|
import engine.gameManager.ZoneManager; |
|
import engine.math.Vector3fImmutable; |
|
import engine.objects.*; |
|
import engine.server.MBServerStatics; |
|
import org.pmw.tinylog.Logger; |
|
|
|
import java.util.HashSet; |
|
import java.util.concurrent.locks.ReadWriteLock; |
|
import java.util.concurrent.locks.ReentrantReadWriteLock; |
|
|
|
/** |
|
* @author Summary: Game designer utility command to purge all |
|
* objects of a given type within a supplied range |
|
*/ |
|
|
|
public class PurgeObjectsCmd extends AbstractDevCmd { |
|
|
|
// Instance variables |
|
|
|
private Vector3fImmutable _currentLocation; |
|
private float _targetRange; |
|
private int _targetMask; |
|
|
|
// Concurrency support |
|
|
|
private ReadWriteLock lock = new ReentrantReadWriteLock(); |
|
|
|
// Constructor |
|
|
|
public PurgeObjectsCmd() { |
|
super("purge"); |
|
} |
|
|
|
private static void PurgeWalls(Zone zone, PlayerCharacter pc) { |
|
|
|
if (!zone.isPlayerCity()) |
|
return; |
|
|
|
for (Building building : zone.zoneBuildingSet) { |
|
if (!BuildingManager.IsWallPiece(building)) |
|
continue; |
|
for (AbstractCharacter ac : building.getHirelings().keySet()) { |
|
NPC npc = null; |
|
Mob mobA = null; |
|
|
|
if (ac.getObjectType() == GameObjectType.NPC) |
|
npc = (NPC) ac; |
|
else if (ac.getObjectType() == GameObjectType.Mob) |
|
mobA = (Mob) ac; |
|
|
|
|
|
if (npc != null) { |
|
for (Integer minionUUID : npc.minions) { |
|
Mob mob = Mob.getMob(minionUUID); |
|
WorldGrid.RemoveWorldObject(mob); |
|
WorldGrid.removeObject(mob, pc); |
|
|
|
if (mob.getParentZone() != null) |
|
mob.getParentZone().zoneMobSet.remove(mob); |
|
} |
|
|
|
DbManager.NPCQueries.DELETE_NPC(npc); |
|
DbManager.removeFromCache(GameObjectType.NPC, |
|
npc.getObjectUUID()); |
|
WorldGrid.RemoveWorldObject(npc); |
|
} else if (mobA != null) { |
|
for (Integer minionUUID : mobA.minions) { |
|
Mob mob = Mob.getMob(minionUUID); |
|
WorldGrid.RemoveWorldObject(mob); |
|
WorldGrid.removeObject(mob, pc); |
|
|
|
if (mob.getParentZone() != null) |
|
mob.getParentZone().zoneMobSet.remove(mob); |
|
} |
|
DbManager.MobQueries.DELETE_MOB(mobA); |
|
DbManager.removeFromCache(GameObjectType.Mob, |
|
mobA.getObjectUUID()); |
|
WorldGrid.RemoveWorldObject(mobA); |
|
} |
|
|
|
} |
|
|
|
|
|
DbManager.BuildingQueries.DELETE_FROM_DATABASE(building); |
|
DbManager.removeFromCache(building); |
|
WorldGrid.RemoveWorldObject(building); |
|
WorldGrid.removeObject(building, pc); |
|
} |
|
|
|
} |
|
|
|
|
|
// AbstractDevCmd Overridden methods |
|
|
|
private static boolean validateUserInput(String[] userInput) { |
|
|
|
int stringIndex; |
|
String commandSet = "npcmobmeshall"; |
|
|
|
// incorrect number of arguments test |
|
|
|
if (userInput.length != 2) |
|
return false; |
|
|
|
// Test of game object type argument |
|
|
|
stringIndex = commandSet.indexOf(userInput[0].toLowerCase()); |
|
|
|
if (stringIndex == -1) |
|
return false; |
|
|
|
// Test if range argument can convert to a float |
|
|
|
try { |
|
Float.parseFloat(userInput[1]); |
|
} catch (NumberFormatException | NullPointerException e) { |
|
return false; |
|
} |
|
|
|
// User input passes validation |
|
|
|
return true; |
|
} |
|
|
|
private static void removeBuilding(PlayerCharacter pc, Building building) { |
|
|
|
if ((building.getBlueprintUUID() != 0) && |
|
(building.getBlueprint().getBuildingGroup() == BuildingGroup.TOL)) |
|
return; |
|
if ((building.getBlueprintUUID() != 0) && |
|
(building.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE)) |
|
Shrine.RemoveShrineFromCacheByBuilding(building); |
|
|
|
if ((building.getBlueprint() != null) && (building.getBlueprint().getBuildingGroup() == BuildingGroup.SPIRE)) |
|
building.disableSpire(false); |
|
|
|
for (AbstractCharacter ac : building.getHirelings().keySet()) { |
|
NPC npc = null; |
|
Mob mobA = null; |
|
|
|
if (ac.getObjectType() == GameObjectType.NPC) |
|
npc = (NPC) ac; |
|
else if (ac.getObjectType() == GameObjectType.Mob) |
|
mobA = (Mob) ac; |
|
|
|
|
|
if (npc != null) { |
|
for (Integer minionUUID : npc.minions) { |
|
Mob mob = Mob.getMob(minionUUID); |
|
WorldGrid.RemoveWorldObject(mob); |
|
WorldGrid.removeObject(mob, pc); |
|
|
|
if (mob.getParentZone() != null) |
|
mob.getParentZone().zoneMobSet.remove(mob); |
|
} |
|
DbManager.NPCQueries.DELETE_NPC(npc); |
|
DbManager.removeFromCache(Enum.GameObjectType.NPC, |
|
npc.getObjectUUID()); |
|
WorldGrid.RemoveWorldObject(npc); |
|
} else if (mobA != null) { |
|
for (Integer minionUUID : mobA.minions) { |
|
Mob mob = Mob.getMob(minionUUID); |
|
WorldGrid.RemoveWorldObject(mob); |
|
WorldGrid.removeObject(mob, pc); |
|
|
|
if (mob.getParentZone() != null) |
|
mob.getParentZone().zoneMobSet.remove(mob); |
|
} |
|
DbManager.MobQueries.DELETE_MOB(mobA); |
|
DbManager.removeFromCache(Enum.GameObjectType.Mob, |
|
mobA.getObjectUUID()); |
|
WorldGrid.RemoveWorldObject(mobA); |
|
} |
|
|
|
} |
|
|
|
|
|
DbManager.BuildingQueries.DELETE_FROM_DATABASE(building); |
|
DbManager.removeFromCache(building); |
|
WorldGrid.RemoveWorldObject(building); |
|
WorldGrid.removeObject(building, pc); |
|
} |
|
|
|
private static void removeNPC(PlayerCharacter pc, NPC npc) { |
|
DbManager.NPCQueries.DELETE_NPC(npc); |
|
DbManager.removeFromCache(npc); |
|
WorldGrid.RemoveWorldObject(npc); |
|
WorldGrid.removeObject(npc, pc); |
|
} |
|
|
|
// Class methods |
|
|
|
private static void removeMob(PlayerCharacter pc, Mob mob) { |
|
mob.setLoc(Vector3fImmutable.ZERO); //Move it off the plane.. |
|
mob.setBindLoc(Vector3fImmutable.ZERO); //Reset the bind loc.. |
|
//mob.setHealth(-1, pc); //Kill it! |
|
|
|
DbManager.MobQueries.DELETE_MOB(mob); |
|
DbManager.removeFromCache(mob); |
|
WorldGrid.RemoveWorldObject(mob); |
|
WorldGrid.removeObject(mob, pc); |
|
} |
|
|
|
@Override |
|
protected void _doCmd(PlayerCharacter pc, String[] args, |
|
AbstractGameObject target) { |
|
|
|
// Grab write lock due to use of instance variables |
|
|
|
lock.writeLock().lock(); |
|
|
|
try { |
|
|
|
if (args[0].toLowerCase().equals("walls")) { |
|
Zone zone = ZoneManager.findSmallestZone(pc.getLoc()); |
|
|
|
PurgeWalls(zone, pc); |
|
return; |
|
} |
|
|
|
if (validateUserInput(args) == false) { |
|
this.sendUsage(pc); |
|
return; |
|
} |
|
|
|
parseUserInput(args); |
|
|
|
// Arguments have been validated and parsed at this point |
|
// Build array of requested objects |
|
|
|
_currentLocation = pc.getLoc(); |
|
|
|
HashSet<AbstractWorldObject> objectList = |
|
WorldGrid.getObjectsInRangePartial(_currentLocation, _targetRange, _targetMask); |
|
|
|
// Iterate through array and remove objects from game world and database |
|
|
|
for (AbstractWorldObject awo : objectList) { |
|
|
|
switch (awo.getObjectType()) { |
|
case Building: |
|
removeBuilding(pc, (Building) awo); |
|
break; |
|
case NPC: |
|
removeNPC(pc, (NPC) awo); |
|
break; |
|
case Mob: |
|
removeMob(pc, (Mob) awo); |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
// Send results to user |
|
throwbackInfo(pc, "Purge: " + objectList.size() + " objects were removed in range " + _targetRange); |
|
} catch (Exception e) { |
|
Logger.error(e); |
|
} |
|
|
|
// Release Reentrant lock |
|
|
|
finally { |
|
lock.writeLock().unlock(); |
|
} |
|
} |
|
|
|
@Override |
|
protected String _getHelpString() { |
|
return "Purges game objects within range"; |
|
} |
|
|
|
@Override |
|
protected String _getUsageString() { |
|
return "/purge [npc|mob|mesh|all] [range <= 200]"; |
|
} |
|
|
|
private void parseUserInput(String[] userInput) { |
|
|
|
_targetMask = 0; |
|
_targetRange = 0f; |
|
|
|
// Build mask from user input |
|
|
|
switch (userInput[0].toLowerCase()) { |
|
case "npc": |
|
_targetMask = MBServerStatics.MASK_NPC; |
|
break; |
|
case "mob": |
|
_targetMask = MBServerStatics.MASK_MOB; |
|
break; |
|
case "mesh": |
|
_targetMask = MBServerStatics.MASK_BUILDING; |
|
break; |
|
case "all": |
|
_targetMask = MBServerStatics.MASK_NPC | MBServerStatics.MASK_MOB | MBServerStatics.MASK_BUILDING; |
|
break; |
|
default: |
|
break; |
|
} |
|
|
|
// Parse second argument into range parameter. Cap at 200 units. |
|
|
|
_targetRange = Float.parseFloat(userInput[1]); |
|
_targetRange = Math.min(_targetRange, 200f); |
|
} |
|
|
|
}
|
|
|