Files
Server/src/engine/net/client/handlers/ActivateNPCMsgHandler.java
T
MagicBotandClaude Opus 5.5 c774746736 Read deed consumers from DeedTemplate
Deed placement (ObjectActionMsgHandler, PlaceAssetMsgHandler) reads
deed_structure_id from DeedTemplate._deeds. The deed, employment
contract and charter type checks (PlaceAssetMsgHandler,
ActivateNPCMsgHandler, GuildCreationFinalizeHandler, UseCharterMsg,
Item.serialize) read item_type through the cache template bridge.
Charters go through the shared getter rather than _deeds because
template 545 "Charter" is a CHARTER in the ITEM folder.

Parity (offline, static_item_templates vs COBJECTS, scripts/p13.py,
881 templates: all 880 DEED plus ITEM 545): 0 differences in
item_type and deed_structure_id. Every DB DEED, EMPLOYMENTCONTRACT,
PETTOTEM and FURNITUREDEED id is in the DEED folder. No value changes
expected. No pet totem or furniture deed consumer reads template
fields, so neither changes.

JSON-Refactor-Plan Task 1.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 11:42:54 -04:00

135 lines
4.2 KiB
Java

package engine.net.client.handlers;
import engine.gameManager.*;
import engine.mbEnums;
import engine.mbEnums.ItemType;
import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ActivateNPCMessage;
import engine.net.client.msg.ClientNetMsg;
import engine.net.client.msg.ManageCityAssetsMsg;
import engine.objects.*;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
/*
* @Author:
* @Summary: Processes application protocol message which keeps
* client's tcp connection open.
*/
public class ActivateNPCMsgHandler extends AbstractClientMsgHandler {
public ActivateNPCMsgHandler() {
super();
}
@Override
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) {
ActivateNPCMessage msg;
PlayerCharacter player;
Building building;
Contract contract;
CharacterItemManager itemMan;
Zone zone;
msg = (ActivateNPCMessage) baseMsg;
player = SessionManager.getPlayerCharacter(origin);
building = BuildingManager.getBuildingFromCache(msg.buildingUUID());
if (player == null || building == null)
return false;
ArrayList<Item> ItemLists = new ArrayList<>();
// Filter hirelings by slot type
for (Item hirelings : player.getInventory()) {
if (hirelings.template.cacheTemplate.getItemType().equals(ItemType.EMPLOYMENTCONTRACT)) {
contract = DbManager.ContractQueries.GET_CONTRACT(hirelings.templateID);
if (contract == null)
continue;
if (contract.canSlotinBuilding(building))
ItemLists.add(hirelings);
}
}
if (msg.getUnknown01() == 1) {
//Request npc list to slot
ActivateNPCMessage anm = new ActivateNPCMessage();
anm.setSize(ItemLists.size());
anm.setItemList(ItemLists);
Dispatch dispatch = Dispatch.borrow(player, anm);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
}
if (msg.getUnknown01() == 0) {
//Slot npc
if (building.getBlueprintUUID() == 0) {
ChatManager.chatSystemError(player, "Unable to load Blueprint for Building Mesh " + building.getMeshUUID());
return false;
}
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size())
return false;
Item contractItem = Item.getFromCache(msg.getContractItem());
if (contractItem == null)
return false;
if (!player.charItemManager.doesCharOwnThisItem(contractItem.getObjectUUID())) {
Logger.error(player.getName() + "has attempted to place Hireling : " + contractItem.getName() + "without a valid contract!");
return false;
}
itemMan = player.charItemManager;
zone = ZoneManager.findSmallestZone(building.getLoc());
if (zone == null)
return false;
contract = DbManager.ContractQueries.GET_CONTRACT(contractItem.templateID);
if (contract == null)
return false;
// Check if contract can be slotted in this building
if (contract.canSlotinBuilding(building) == false)
return false;
if (!BuildingManager.addHireling(building, player, zone, contract, contractItem))
return false;
itemMan.delete(contractItem);
itemMan.updateInventory();
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, building);
mca1.actionType = 3;
mca1.setTargetType(building.getObjectType().ordinal());
mca1.setTargetID(building.getObjectUUID());
mca1.setTargetType3(building.getObjectType().ordinal());
mca1.setTargetID3(building.getObjectUUID());
mca1.setAssetName1(building.getName());
mca1.setUnknown54(1);
Dispatch dispatch = Dispatch.borrow(player, mca1);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
}
return true;
}
}