Refuse dev commands that would change static world objects

World Boot Task 0.6. Static objects are built from client data each boot,
so dev commands answer "Must use external tooling to modify gameworld" and
log the command, target and caller instead of changing them.

- /addbuilding, /mob and /npc always refuse (addsWorldContent hook in doCmd).
- rotate, pull, setbuildingaltitude, remove, rename, npcname, setowner,
  setguild, setrank and forcerename refuse a static target.
- purge skips static objects and reports how many it skipped.

Value changes: none for non-static objects; the purge message now also
reports the skipped count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-27 18:57:40 -04:00
1 parent 49ad45d179
commit bd3787f9d5
15 files changed
+97 -1

No files matched your search

+25
View File
@@ -13,6 +13,7 @@ import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.mbEnums.GameObjectType;
import engine.objects.*;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
@@ -99,12 +100,18 @@ public abstract class AbstractDevCmd {
if (args.length > 0 && args[0].equalsIgnoreCase("?")) {
this.sendHelp(pcSender);
this.sendUsage(pcSender);
} else if (this.addsWorldContent()) {
this.refuseWorldChange(pcSender, target);
} else {
this.tr = target;
this._doCmd(pcSender, args, target);
}
}
protected boolean addsWorldContent() {
return false;
}
protected abstract void _doCmd(PlayerCharacter pcSender, String[] args,
AbstractGameObject target);
@@ -178,4 +185,22 @@ public abstract class AbstractDevCmd {
ChatManager.chatSystemInfo(pc, msgText);
}
// Static world objects are built from client data each boot, so they are changed with external tooling only.
protected boolean refuseStaticTarget(PlayerCharacter pc, AbstractGameObject target) {
if (!(target instanceof AbstractWorldObject) || !((AbstractWorldObject) target).isStaticWorldObject())
return false;
this.refuseWorldChange(pc, target);
return true;
}
protected void refuseWorldChange(PlayerCharacter pc, AbstractGameObject target) {
String targetText = (target == null) ? "no target" : target.getObjectType() + " " + target.getObjectUUID();
this.throwbackError(pc, "Must use external tooling to modify gameworld");
Logger.info("Refused dev command " + this.getMainCmdString() + " on " + targetText + " by " + pc.getFirstName());
}
}
@@ -108,6 +108,11 @@ public class AddBuildingCmd extends AbstractDevCmd {
}
@Override
protected boolean addsWorldContent() {
return true;
}
@Override
protected String _getHelpString() {
return "Creates a building of type 'buildingID' at the location your character is standing.";
+5
View File
@@ -75,6 +75,11 @@ public class AddMobCmd extends AbstractDevCmd {
}
}
@Override
protected boolean addsWorldContent() {
return true;
}
@Override
protected String _getHelpString() {
return "Creates a Mob of type 'mobID' at the location your character is standing";
+5
View File
@@ -94,6 +94,11 @@ public class AddNPCCmd extends AbstractDevCmd {
}
}
@Override
protected boolean addsWorldContent() {
return true;
}
@Override
protected String _getHelpString() {
return "Creates an NPC of type 'npcID' at the location your character is standing";
+3
View File
@@ -66,6 +66,9 @@ public class PullCmd extends AbstractDevCmd {
return;
}
if (this.refuseStaticTarget(pcSender, target))
return;
targetLoc = pcSender.getLoc();
serverZone = ZoneManager.findSmallestZone(targetLoc);
switch (target.getObjectType()) {
+8 -1
View File
@@ -245,11 +245,17 @@ public class PurgeObjectsCmd extends AbstractDevCmd {
HashSet<AbstractWorldObject> objectList =
WorldGrid.getObjectsInRangePartial(_currentLocation, _targetRange, _targetMask);
int staticSkipped = 0;
// Iterate through array and remove objects from game world and database
for (AbstractWorldObject awo : objectList) {
if (awo.isStaticWorldObject()) {
staticSkipped++;
continue;
}
switch (awo.getObjectType()) {
case Building:
removeBuilding(pc, (Building) awo);
@@ -266,7 +272,8 @@ public class PurgeObjectsCmd extends AbstractDevCmd {
}
// Send results to user
throwbackInfo(pc, "Purge: " + objectList.size() + " objects were removed in range " + _targetRange);
throwbackInfo(pc, "Purge: " + (objectList.size() - staticSkipped) + " objects were removed in range " + _targetRange
+ ", " + staticSkipped + " static objects skipped");
} catch (Exception e) {
Logger.error(e);
}
@@ -119,6 +119,9 @@ public class RemoveObjectCmd extends AbstractDevCmd {
private void removeBuilding(PlayerCharacter pc, Building building) {
if (this.refuseStaticTarget(pc, building))
return;
Zone currentZone = ZoneManager.findSmallestZone(pc.getLoc());
if (currentZone == null) {
@@ -164,6 +167,9 @@ public class RemoveObjectCmd extends AbstractDevCmd {
private void removeNPC(PlayerCharacter pc, NPC npc) {
if (this.refuseStaticTarget(pc, npc))
return;
Zone currentZone = ZoneManager.findSmallestZone(pc.getLoc());
if (currentZone == null) {
this.throwbackError(pc, "Could not locate zone for player.");
@@ -196,6 +202,9 @@ public class RemoveObjectCmd extends AbstractDevCmd {
private void removeMob(PlayerCharacter pc, Mob mob) {
if (this.refuseStaticTarget(pc, mob))
return;
Zone currentZone = ZoneManager.findSmallestZone(pc.getLoc());
if (currentZone == null) {
+4
View File
@@ -47,6 +47,10 @@ public class RenameCmd extends AbstractDevCmd {
building = (Building) target;
} else
npc = getTargetAsNPC(pcSender);
if (this.refuseStaticTarget(pcSender, npc) || this.refuseStaticTarget(pcSender, building))
return;
if (npc != null) {
DbManager.NPCQueries.SET_PROPERTY(npc, "npc_name", args[0]);
String name = args[0];
+12
View File
@@ -186,6 +186,10 @@ public class RotateCmd extends AbstractDevCmd {
}
private void rotateBuilding(PlayerCharacter pc, Building building, float yaw) {
if (this.refuseStaticTarget(pc, building))
return;
building.setRotation(Quaternion.fromYaw(yaw));
building.getBounds().setBounds(building);
WorldGrid.updateObject(building, pc);
@@ -196,6 +200,10 @@ public class RotateCmd extends AbstractDevCmd {
}
private void rotateNPC(PlayerCharacter pc, NPC npc, float yaw) {
if (this.refuseStaticTarget(pc, npc))
return;
npc.setRotation(characterRotation(yaw));
DbManager.NPCQueries.SET_PROPERTY(npc, "npc_rotation", npc.getRotation().w);
WorldGrid.updateObject(npc, pc);
@@ -204,6 +212,10 @@ public class RotateCmd extends AbstractDevCmd {
}
private void rotateMob(PlayerCharacter pc, Mob mob, float yaw) {
if (this.refuseStaticTarget(pc, mob))
return;
mob.setRotation(characterRotation(yaw));
DbManager.MobQueries.SET_PROPERTY(mob, "mob_rotation", mob.getRotation().w);
WorldGrid.updateObject(mob, pc);
@@ -66,6 +66,9 @@ public class SetBuildingAltitudeCmd extends AbstractDevCmd {
Building targetBuilding = (Building) target;
if (this.refuseStaticTarget(pc, targetBuilding))
return;
float altitude = 0;
try {
@@ -36,6 +36,8 @@ public class SetForceRenameCityCmd extends AbstractDevCmd {
City city = City.getCity(zone.playerCityUUID);
if (city == null)
return;
if (this.refuseStaticTarget(pc, city))
return;
city.setForceRename(rename);
}
+3
View File
@@ -37,6 +37,9 @@ public class SetGuildCmd extends AbstractDevCmd {
targetNPC = getTargetAsNPC(pcSender);
targetGuild = Guild.getGuild(Integer.parseInt(args[0]));
if (this.refuseStaticTarget(pcSender, targetNPC))
return;
DbManager.NPCQueries.SET_PROPERTY(targetNPC, "npc_guildID", args[0]);
targetNPC.setGuild(targetGuild);
@@ -41,6 +41,9 @@ public class SetNpcNameCmd extends AbstractDevCmd {
NPC npc = (NPC) target;
if (this.refuseStaticTarget(pc, npc))
return;
String name = words[0];
NPC.UpdateName(npc, name);
+3
View File
@@ -35,6 +35,9 @@ public class SetOwnerCmd extends AbstractDevCmd {
_targetBuilding = getTargetAsBuilding(pcSender);
if (this.refuseStaticTarget(pcSender, _targetBuilding))
return;
// if it's a tol change ownership of the city
if (_targetBuilding.getBlueprint() != null &&
+7
View File
@@ -51,6 +51,10 @@ public class SetRankCmd extends AbstractDevCmd {
}
if (target != null) {
if (this.refuseStaticTarget(player, target))
return;
switch (target.getObjectType()) {
case Building:
Building targetBuilding = (Building) target;
@@ -99,6 +103,9 @@ public class SetRankCmd extends AbstractDevCmd {
return;
}
if (this.refuseStaticTarget(player, targetBuilding))
return;
Blueprint blueprint = targetBuilding.getBlueprint();
if (blueprint == null) {