package engine.net.client.handlers; import engine.Enum; import engine.Enum.BuildingGroup; import engine.Enum.DispatchChannel; import engine.Enum.ItemType; import engine.InterestManagement.RealmMap; import engine.InterestManagement.WorldGrid; import engine.exception.MsgSendException; import engine.gameManager.*; import engine.math.Bounds; import engine.math.Vector3fImmutable; import engine.net.Dispatch; import engine.net.DispatchMessage; import engine.net.client.ClientConnection; import engine.net.client.msg.*; import engine.objects.*; import engine.powers.PowersBase; import org.pmw.tinylog.Logger; import java.util.ArrayList; import java.util.concurrent.locks.ReentrantReadWriteLock; /* * @Author: * @Summary: Processes application protocol message which actives * items such as charters and deeds in the character's inventory */ public class ObjectActionMsgHandler extends AbstractClientMsgHandler { // Reentrant lock for dropping banes private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public ObjectActionMsgHandler() { super(ObjectActionMsg.class); } private static boolean claimRealm(PlayerCharacter player, int charterUUID) { Guild guild; Realm realm; City city; Building tol; float hPMod; Warehouse warehouse; boolean hasResources = true; int resourceValue; if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) { ErrorPopupMsg.sendErrorPopup(player, 176); // Only guild leaders can claim a territory return false; } guild = player.getGuild(); city = guild.getOwnedCity(); if (city == null) { ErrorPopupMsg.sendErrorPopup(player, 179); // Only landed guilds may claim a territory return false; } if (city.isLocationOnCityGrid(player.getLoc()) == false) { ErrorPopupMsg.sendErrorPopup(player, 186); // Your tree is not inside a territory! return false; } tol = city.getTOL(); if (tol.getRank() != 7) { ErrorPopupMsg.sendErrorPopup(player, 181); // Your tree must be rank 7 before claiming a territory return false; } realm = RealmMap.getRealmForCity(city); if (realm.getCanBeClaimed() == false) { ErrorPopupMsg.sendErrorPopup(player, 180); // This territory cannot be ruled by anyone return false; } if (realm.isRuled() == true) { ErrorPopupMsg.sendErrorPopup(player, 178); // This territory is already claimed return false; } if (!Realm.HasAllBlessings(player)) { ErrorPopupMsg.sendErrorPopup(player, 185); // You must seek the blessing of the three sages before you can rule return false; } // Must have the required resources in warehouse to claim realm warehouse = city.getWarehouse(); if (warehouse == null) { ErrorPopupMsg.sendErrorPopup(player, 188); // You must have a warehouse to become a capital return false; } resourceValue = warehouse.getResources().get(Warehouse.goldIB); if (resourceValue < 5000000) hasResources = false; resourceValue = warehouse.getResources().get(Warehouse.stoneIB); if (resourceValue < 8000) hasResources = false; resourceValue = warehouse.getResources().get(Warehouse.lumberIB); if (resourceValue < 8000) hasResources = false; resourceValue = warehouse.getResources().get(Warehouse.galvorIB); if (resourceValue < 15) hasResources = false; resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB); if (resourceValue < 15) hasResources = false; resourceValue = warehouse.getResources().get(Warehouse.mithrilIB); if (resourceValue < 1) hasResources = false; if (hasResources == false) { ErrorPopupMsg.sendErrorPopup(player, 184); // Insufficient gold or resources to upgrade to capital return false; } // Remove resources from warehouse before claiming realm resourceValue = warehouse.getResources().get(Warehouse.goldIB); if (DbManager.WarehouseQueries.updateGold(warehouse, resourceValue - 5000000) == true) { warehouse.getResources().put(Warehouse.goldIB, resourceValue - 5000000); warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.GOLD, 5000000); } else { Logger.error("gold update failed for warehouse of UUID:" + warehouse.getObjectUUID()); return false; } resourceValue = warehouse.getResources().get(Warehouse.stoneIB); if (DbManager.WarehouseQueries.updateStone(warehouse, resourceValue - 8000) == true) { warehouse.getResources().put(Warehouse.stoneIB, resourceValue - 8000); warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.STONE, 8000); } else { Logger.error("stone update failed for warehouse of UUID:" + warehouse.getObjectUUID()); return false; } resourceValue = warehouse.getResources().get(Warehouse.lumberIB); if (DbManager.WarehouseQueries.updateLumber(warehouse, resourceValue - 8000) == true) { warehouse.getResources().put(Warehouse.lumberIB, resourceValue - 8000); warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.LUMBER, 8000); } else { Logger.error("lumber update failed for warehouse of UUID:" + warehouse.getObjectUUID()); return false; } resourceValue = warehouse.getResources().get(Warehouse.galvorIB); if (DbManager.WarehouseQueries.updateGalvor(warehouse, resourceValue - 15) == true) { warehouse.getResources().put(Warehouse.galvorIB, resourceValue - 15); warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.GALVOR, 15); } else { Logger.error("galvor update failed for warehouse of UUID:" + warehouse.getObjectUUID()); return false; } resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB); if (DbManager.WarehouseQueries.updateWormwood(warehouse, resourceValue - 15) == true) { warehouse.getResources().put(Warehouse.wormwoodIB, resourceValue - 15); warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.WORMWOOD, 15); } else { Logger.error("wormwood update failed for warehouse of UUID:" + warehouse.getObjectUUID()); return false; } resourceValue = warehouse.getResources().get(Warehouse.mithrilIB); if (DbManager.WarehouseQueries.updateWormwood(warehouse, resourceValue - 1) == true) { warehouse.getResources().put(Warehouse.mithrilIB, resourceValue - 1); warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.MITHRIL, 1); } else { Logger.error("wormwood update failed for warehouse of UUID:" + warehouse.getObjectUUID()); return false; } realm.claimRealmForCity(city, charterUUID); tol.setRank(8); WorldGrid.updateObject(tol); for (Building building : city.getParent().zoneBuildingSet) { if (building.getBlueprintUUID() != 0) { // TOL Health set through regular linear equation if (building.getBlueprint().getBuildingGroup() == BuildingGroup.TOL) { continue; } hPMod = (building.getMaxHitPoints() * Realm.getRealmHealthMod(city)); building.setMaxHitPoints(building.getMaxHitPoints() + hPMod); } } if (!guild.getNation().equals(guild)) { guild.getNation().setRealmsOwned(guild.getNation().getRealmsOwned() + 1); GuildManager.updateAllGuildTags(guild.getNation()); } guild.setRealmsOwned(guild.getRealmsOwned() + 1); GuildManager.updateAllGuildTags(guild); removeAllBlessings(player); return true; } private static void removeAllBlessings(PlayerCharacter player) { PowersBase[] powers = new PowersBase[3]; powers[0] = PowersManager.getPowerByIDString("BLS-POWER"); powers[1] = PowersManager.getPowerByIDString("BLS-FORTUNE"); powers[2] = PowersManager.getPowerByIDString("BLS-WISDOM"); for (PowersBase power : powers) { PowersManager.removeEffect(player, power.getActions().get(0), true, false); } } private static void removeRune(PlayerCharacter pc, ClientConnection origin, int runeID) { if (pc == null || origin == null) { return; } //remove only if rune is discipline if (runeID < 3001 || runeID > 3048) { return; } //see if pc has rune ArrayList runes = pc.getRunes(); if (runes == null) return; CharacterRune found = pc.getRune(runeID); if (found == null) return; //TODO see if player needs to refine skills or powers first //attempt remove rune from player if (!CharacterRune.removeRune(pc, runeID)) return; //update client with removed rune. ApplyRuneMsg arm = new ApplyRuneMsg(pc.getObjectType().ordinal(), pc.getObjectUUID(), runeID); Dispatch dispatch = Dispatch.borrow(pc, arm); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); } // Handle activation of tears of seadron: Removes rune from player. @Override protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException { // Member variable declaration ObjectActionMsg msg; PlayerCharacter player; CharacterItemManager itemMan; ArrayList comps; Dispatch dispatch; boolean waterbucketBypass = false; // Member variable assignment msg = (ObjectActionMsg) baseMsg; player = SessionManager.getPlayerCharacter(origin); if (player == null) { return true; } itemMan = player.getCharItemManager(); if (itemMan == null) { return true; } comps = msg.getTargetCompID(); if (comps.isEmpty()) { return true; } long comp = comps.get(0); if (((int) comp) != 0) { Item item = Item.getFromCache((int) comp); if (item == null) { return true; } //dupe check if (!item.validForInventory(origin, player, itemMan)) { return true; } ItemBase ib = item.getItemBase(); if (ib == null) { return true; } if (itemMan.doesCharOwnThisItem(item.getObjectUUID())) { if (ib.isConsumable() || ib.getType() == ItemType.FARMABLE) { int uuid = ib.getUUID(); int type = ib.getType().getValue(); switch (type) { case 27: //Mithril repair break; case 10: //charters //don't think they're handled here? break; case 19: //buildings //Call add building screen here, ib.getUseID() get's building ID //if inside player city, center loc on tol. otherwise center on player. Vector3fImmutable loc = player.getLoc(); Zone zone = ZoneManager.findSmallestZone(player.getLoc()); if (zone != null) { if (zone.isPlayerCity()) { loc = zone.getLoc(); } } PlaceAssetMsg pam = new PlaceAssetMsg(); pam.setActionType(2); pam.setContractID(item.getObjectUUID()); pam.setX(loc.getX() + 64); //offset grid from tol pam.setY(loc.getY()); pam.setZ(loc.getZ() + 64); //offset grid from tol pam.addPlacementInfo(ib.getUseID()); dispatch = Dispatch.borrow(player, pam); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); //itemMan.consume(item); //temporary fix for dupe.. TODO Make Item Unusable after This message is sent. break; case 25: //furniture //Call add furniture screen here. ib.getUseID() get's furniture ID break; case 33: long shrineCompID = comps.get(1); Building shrineBuilding = BuildingManager.getBuilding((int) shrineCompID); if (shrineBuilding == null) { return true; } if (shrineBuilding.getBlueprint() != null && shrineBuilding.getBlueprint().getBuildingGroup() != engine.Enum.BuildingGroup.SHRINE) { return true; } if (shrineBuilding.getRank() == -1) { return true; } Shrine shrine = Shrine.shrinesByBuildingUUID.get(shrineBuilding.getObjectUUID()); if (shrine == null) { return true; } if (shrine.addFavor(player, item)) { shrineBuilding.addEffectBit(1000000 << 2); shrineBuilding.updateEffects(); shrineBuilding.removeEffectBit(1000000 << 2); } break; case 35: int charterType = 0; switch (uuid) { case 910020: charterType = 762228431; break; case 910021: charterType = -15978914; break; case 910022: charterType = -600065291; break; } if (claimRealm(player, charterType) == true) { itemMan.consume(item); } break; case 7: //rod of command long compID = comps.get(1); int objectType = AbstractWorldObject.extractTypeID(compID).ordinal(); Mob toCommand; if (objectType == engine.Enum.GameObjectType.Mob.ordinal()) { toCommand = Mob.getFromCache((int) compID); } //Only Command Mob Types. else { return true; } if (toCommand == null) { return true; } if (!toCommand.isSiege()) return true; if (player.commandSiegeMinion(toCommand)) { itemMan.consume(item); } break; //ANNIVERSERY GIFT case 31: // *** Disabled for now: Needs bootyset created //if (ib.getUUID() == 971012) { // int random = ThreadLocalRandom.current().nextInt(ItemBase.AnniverseryGifts.size()); // int annyID = ItemBase.AnniverseryGifts.get(random); // ItemBase annyIB = ItemBase.getItemBase(annyID); // if (annyIB != null) { // Item gift = MobLoot.createItemForPlayer(player, annyIB); // if (gift != null) { // itemMan.addItemToInventory(gift); // itemMan.consume(item); // } // } // break; //} LootManager.peddleFate(player,item); break; case 30: //water bucket case 8: //potions, tears of saedron case 5: //runes, petition, warrant, scrolls if (uuid > 3000 && uuid < 3050) { //Discipline Runes if (ApplyRuneMsg.applyRune(uuid, origin, player)) { itemMan.consume(item); } break; } else if (uuid > 249999 && uuid < 250123) { //stat and mastery runes if (ApplyRuneMsg.applyRune(uuid, origin, player)) { itemMan.consume(item); } break; } else if (uuid > 250114 && uuid < 250123) { //mastery runes if (ApplyRuneMsg.applyRune(uuid, origin, player)) { itemMan.consume(item); } break; } else if (uuid > 252122 && uuid < 252128) { //mastery runes if (ApplyRuneMsg.applyRune(uuid, origin, player)) { itemMan.consume(item); } break; } else if (uuid > 680069 && uuid < 680074) //Handle Charter, Deed, Petition, Warrant here { break; } else if (uuid > 910010 && uuid < 910019) { int rank = uuid - 910010; if (rank < 1 || rank > 8) { ChatManager.chatSystemError(player, "Invalid Rank for bane scroll!"); return true; } // Only one banestone at a time lock.writeLock().lock(); try { if (Bane.summonBanestone(player, origin, rank) == true) itemMan.consume(item); } finally { lock.writeLock().unlock(); } break; } else if (uuid == 910010) { //tears of saedron if (comps.size() > 1) { removeRune(player, origin, comps.get(1).intValue()); } break; } else if (item.getChargesRemaining() > 0) { ArrayList tarList = msg.getTargetCompID(); AbstractWorldObject target = player; if (tarList.size() > 1) { long tarID = tarList.get(1); if (tarID != 0) { AbstractGameObject tarAgo = AbstractGameObject.getFromTypeAndID(tarID); if (tarAgo != null && tarAgo instanceof AbstractWorldObject) { target = (AbstractWorldObject) tarAgo; } } } // Bypass for waterbuckets // test character targeted if (ib.getUUID() == 910005) { // test for valid target type if (target.getObjectType() == Enum.GameObjectType.PlayerCharacter) waterbucketBypass = true; else { // test distance to structure Building targetBuilding = (Building) target; Bounds testBounds = Bounds.borrow(); testBounds.setBounds(player.getLoc(), 25); if (Bounds.collide(targetBuilding.getBounds(), testBounds, .1f) == false) { ChatManager.chatSystemError(player, "Not in range of structura for to heal!"); return true; } } // Send piss bucket animation VisualUpdateMessage vum = new VisualUpdateMessage(player, 16323); vum.configure(); DispatchMessage.sendToAllInRange(player, vum); } if (waterbucketBypass == false) PowersManager.applyPower(player, target, Vector3fImmutable.ZERO, ib.getUseID(), ib.getUseAmount(), true); itemMan.consume(item); } else //just remove the item at this point itemMan.consume(item); dispatch = Dispatch.borrow(player, msg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); player.cancelOnSpell(); break; default: //shouldn't be here, consume item dispatch = Dispatch.borrow(player, msg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); // itemMan.consume(item); } } } else { // TODO log item does not belong to player // System.out.println("Item does not belong to player"); // Cleanup duped item here } } return true; } }