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>
135 lines
4.2 KiB
Java
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;
|
|
}
|
|
|
|
}
|