|
|
@ -1366,232 +1366,171 @@ public class ClientMessagePump implements NetMsgHandler { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void buyFromNPC(BuyFromNPCMsg msg, ClientConnection origin) { |
|
|
|
private static void buyFromNPC(BuyFromNPCMsg msg, ClientConnection origin) { |
|
|
|
|
|
|
|
|
|
|
|
PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(origin); |
|
|
|
PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(origin); |
|
|
|
|
|
|
|
|
|
|
|
if (sourcePlayer == null) |
|
|
|
if (sourcePlayer == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (origin.buyLock.tryLock()) { |
|
|
|
if (origin.buyLock.tryLock()) { |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
CharacterItemManager itemMan = sourcePlayer.getCharItemManager(); |
|
|
|
CharacterItemManager itemMan = sourcePlayer.getCharItemManager(); |
|
|
|
|
|
|
|
if (itemMan == null) { |
|
|
|
if (itemMan == null) |
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
NPC npc = NPC.getFromCache(msg.getNPCID()); |
|
|
|
NPC npc = NPC.getFromCache(msg.getNPCID()); |
|
|
|
|
|
|
|
if (npc == null) { |
|
|
|
if (npc == null) |
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
Item gold = itemMan.getGoldInventory(); |
|
|
|
Item gold = itemMan.getGoldInventory(); |
|
|
|
|
|
|
|
if (gold == null) { |
|
|
|
if (gold == null) |
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
Item buy = null; |
|
|
|
Item buy = null; |
|
|
|
|
|
|
|
|
|
|
|
if (msg.getItemType() == GameObjectType.MobEquipment.ordinal()) { |
|
|
|
if (msg.getItemType() == GameObjectType.MobEquipment.ordinal()) { |
|
|
|
ArrayList<MobEquipment> sellInventory = npc.getContract().getSellInventory(); |
|
|
|
ArrayList<MobEquipment> sellInventory = npc.getContract().getSellInventory(); |
|
|
|
if (sellInventory == null) |
|
|
|
if (sellInventory == null) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
for (MobEquipment me : sellInventory) { |
|
|
|
for (MobEquipment me : sellInventory) { |
|
|
|
if (me.getObjectUUID() == msg.getItemID()) { |
|
|
|
if (me.getObjectUUID() == msg.getItemID()) { |
|
|
|
ItemBase ib = me.getItemBase(); |
|
|
|
ItemBase ib = me.getItemBase(); |
|
|
|
if (ib == null) |
|
|
|
if (ib == null) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
//test room available for item
|
|
|
|
//test room available for item
|
|
|
|
if (!itemMan.hasRoomInventory(ib.getWeight())) |
|
|
|
if (!itemMan.hasRoomInventory(ib.getWeight())) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
int cost = me.getMagicValue(); |
|
|
|
|
|
|
|
int amountResource = 0; |
|
|
|
|
|
|
|
if(npc.contractUUID == 900){ //resource merchant
|
|
|
|
|
|
|
|
if(ib.getType().equals(ItemType.RESOURCE)) { |
|
|
|
|
|
|
|
amountResource = 15000000 / ib.getBaseValue(); |
|
|
|
|
|
|
|
cost = amountResource * ib.getBaseValue(); |
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
amountResource = 10; |
|
|
|
|
|
|
|
cost = 50000; //elans
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int cost = me.getMagicValue(); |
|
|
|
|
|
|
|
if(npc.getContractID() == 1201 && me.getItemBase().getName().equals("Prospector")) |
|
|
|
|
|
|
|
cost = 50; |
|
|
|
float bargain = sourcePlayer.getBargain(); |
|
|
|
float bargain = sourcePlayer.getBargain(); |
|
|
|
|
|
|
|
|
|
|
|
float profit = npc.getSellPercent(sourcePlayer) - bargain; |
|
|
|
float profit = npc.getSellPercent(sourcePlayer) - bargain; |
|
|
|
|
|
|
|
if(me.getItemBase().getType().equals(ItemType.POTION)) |
|
|
|
|
|
|
|
profit -= 1.0f; |
|
|
|
if (profit < 1) |
|
|
|
if (profit < 1) |
|
|
|
profit = 1; |
|
|
|
profit = 1; |
|
|
|
|
|
|
|
if(npc.getContractID() == 900){ |
|
|
|
|
|
|
|
cost = Warehouse.getCostForResource(ib.getUUID()) * Warehouse.getSellStackSize(ib.getUUID()); |
|
|
|
|
|
|
|
} |
|
|
|
cost *= profit; |
|
|
|
cost *= profit; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (gold.getNumOfItems() - cost < 0) { |
|
|
|
if (gold.getNumOfItems() - cost < 0) { |
|
|
|
//dont' have enough goldItem exit!
|
|
|
|
//dont' have enough goldItem exit!
|
|
|
|
// chatMan.chatSystemInfo(pc, "" + "You dont have enough gold.");
|
|
|
|
// chatMan.chatSystemInfo(pc, "" + "You dont have enough gold.");
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Building b = (!npc.isStatic()) ? npc.getBuilding() : null; |
|
|
|
Building b = (!npc.isStatic()) ? npc.getBuilding() : null; |
|
|
|
|
|
|
|
|
|
|
|
if (b != null && b.getProtectionState().equals(ProtectionState.NPC)) |
|
|
|
if (b != null && b.getProtectionState().equals(ProtectionState.NPC)) |
|
|
|
b = null; |
|
|
|
b = null; |
|
|
|
int buildingDeposit = cost - me.getMagicValue(); |
|
|
|
int buildingDeposit = cost - me.getMagicValue(); |
|
|
|
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold()) { |
|
|
|
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold() && !b.isOwnerIsNPC()) { |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206); |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) { |
|
|
|
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) { |
|
|
|
// chatMan.chatSystemInfo(pc, "" + "You Failed to buy the item.");
|
|
|
|
// chatMan.chatSystemInfo(pc, "" + "You Failed to buy the item.");
|
|
|
|
|
|
|
|
ChatManager.chatSystemError(sourcePlayer, "Failed To Buy Item"); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if(me.getItemBase().getType().equals(ItemType.RESOURCE) && npc.getContractID() == 900){ |
|
|
|
buy = Item.createItemForPlayer(sourcePlayer, ib); |
|
|
|
handleResourcePurchase(me,itemMan,npc,buy,sourcePlayer,ib); |
|
|
|
|
|
|
|
}else { |
|
|
|
if (buy != null) { |
|
|
|
buy = Item.createItemForPlayer(sourcePlayer, ib); |
|
|
|
me.transferEnchants(buy); |
|
|
|
if (buy != null) { |
|
|
|
if(npc.contractUUID == 900){ //resource merchant
|
|
|
|
me.transferEnchants(buy); |
|
|
|
buy.setNumOfItems(amountResource); |
|
|
|
itemMan.addItemToInventory(buy); |
|
|
|
|
|
|
|
if(npc.contractUUID == 900 && buy.getItemBaseID() == 1705032){ |
|
|
|
|
|
|
|
buy.setNumOfItems(10); |
|
|
|
|
|
|
|
DbManager.ItemQueries.UPDATE_NUM_ITEMS(buy,buy.getNumOfItems()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//itemMan.updateInventory();
|
|
|
|
} |
|
|
|
} |
|
|
|
itemMan.addItemToInventory(buy); |
|
|
|
|
|
|
|
//itemMan.updateInventory();
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (msg.getItemType() == GameObjectType.Item.ordinal()) { |
|
|
|
} else if (msg.getItemType() == GameObjectType.Item.ordinal()) { |
|
|
|
|
|
|
|
|
|
|
|
CharacterItemManager npcCim = npc.getCharItemManager(); |
|
|
|
CharacterItemManager npcCim = npc.getCharItemManager(); |
|
|
|
|
|
|
|
|
|
|
|
if (npcCim == null) |
|
|
|
if (npcCim == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
buy = Item.getFromCache(msg.getItemID()); |
|
|
|
buy = Item.getFromCache(msg.getItemID()); |
|
|
|
|
|
|
|
|
|
|
|
if (buy == null) |
|
|
|
if (buy == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
ItemBase ib = buy.getItemBase(); |
|
|
|
ItemBase ib = buy.getItemBase(); |
|
|
|
|
|
|
|
|
|
|
|
if (ib == null) |
|
|
|
if (ib == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (!npcCim.inventoryContains(buy)) |
|
|
|
if (!npcCim.inventoryContains(buy)) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
//test room available for item
|
|
|
|
//test room available for item
|
|
|
|
if (!itemMan.hasRoomInventory(ib.getWeight())) |
|
|
|
if (!itemMan.hasRoomInventory(ib.getWeight())) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
//TODO test cost and subtract goldItem
|
|
|
|
//TODO test cost and subtract goldItem
|
|
|
|
|
|
|
|
|
|
|
|
//TODO CHnage this if we ever put NPc city npcs in buildings.
|
|
|
|
//TODO CHnage this if we ever put NPc city npcs in buildings.
|
|
|
|
int cost = buy.getBaseValue(); |
|
|
|
int cost = buy.getBaseValue(); |
|
|
|
|
|
|
|
|
|
|
|
if (buy.isID() || buy.isCustomValue()) |
|
|
|
if (buy.isID() || buy.isCustomValue()) |
|
|
|
cost = buy.getMagicValue(); |
|
|
|
cost = buy.getMagicValue(); |
|
|
|
|
|
|
|
|
|
|
|
float bargain = sourcePlayer.getBargain(); |
|
|
|
float bargain = sourcePlayer.getBargain(); |
|
|
|
|
|
|
|
|
|
|
|
float profit = npc.getSellPercent(sourcePlayer) - bargain; |
|
|
|
float profit = npc.getSellPercent(sourcePlayer) - bargain; |
|
|
|
|
|
|
|
|
|
|
|
if (profit < 1) |
|
|
|
if (profit < 1) |
|
|
|
profit = 1; |
|
|
|
profit = 1; |
|
|
|
|
|
|
|
|
|
|
|
if (!buy.isCustomValue()) |
|
|
|
if (!buy.isCustomValue()) |
|
|
|
cost *= profit; |
|
|
|
cost *= profit; |
|
|
|
else |
|
|
|
else |
|
|
|
cost = buy.getValue(); |
|
|
|
cost = buy.getValue(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (gold.getNumOfItems() - cost < 0) { |
|
|
|
if (gold.getNumOfItems() - cost < 0) { |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128); // Insufficient Gold
|
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128); // Insufficient Gold
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Building b = (!npc.isStatic()) ? npc.getBuilding() : null; |
|
|
|
Building b = (!npc.isStatic()) ? npc.getBuilding() : null; |
|
|
|
|
|
|
|
|
|
|
|
if (b != null) |
|
|
|
if (b != null) |
|
|
|
if (b.getProtectionState().equals(ProtectionState.NPC)) |
|
|
|
if (b.getProtectionState().equals(ProtectionState.NPC)) |
|
|
|
b = null; |
|
|
|
b = null; |
|
|
|
|
|
|
|
|
|
|
|
int buildingDeposit = cost; |
|
|
|
int buildingDeposit = cost; |
|
|
|
|
|
|
|
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold() && !b.isOwnerIsNPC()) { |
|
|
|
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold()) { |
|
|
|
|
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206); |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) { |
|
|
|
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) { |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 110); |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 110); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (buy != null) |
|
|
|
if (buy != null) |
|
|
|
itemMan.buyFromNPC(buy, npc); |
|
|
|
itemMan.buyFromNPC(buy, npc); |
|
|
|
|
|
|
|
|
|
|
|
} else if (msg.getItemType() == GameObjectType.MobLoot.ordinal()) { |
|
|
|
} else if (msg.getItemType() == GameObjectType.MobLoot.ordinal()) { |
|
|
|
|
|
|
|
|
|
|
|
CharacterItemManager npcCim = npc.getCharItemManager(); |
|
|
|
CharacterItemManager npcCim = npc.getCharItemManager(); |
|
|
|
|
|
|
|
|
|
|
|
if (npcCim == null) |
|
|
|
if (npcCim == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
buy = MobLoot.getFromCache(msg.getItemID()); |
|
|
|
buy = MobLoot.getFromCache(msg.getItemID()); |
|
|
|
|
|
|
|
|
|
|
|
if (buy == null) |
|
|
|
if (buy == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
ItemBase ib = buy.getItemBase(); |
|
|
|
ItemBase ib = buy.getItemBase(); |
|
|
|
|
|
|
|
|
|
|
|
if (ib == null) |
|
|
|
if (ib == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (!npcCim.inventoryContains(buy)) |
|
|
|
if (!npcCim.inventoryContains(buy)) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
//test room available for item
|
|
|
|
//test room available for item
|
|
|
|
if (!itemMan.hasRoomInventory(ib.getWeight())) |
|
|
|
if (!itemMan.hasRoomInventory(ib.getWeight())) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
//TODO test cost and subtract goldItem
|
|
|
|
//TODO test cost and subtract goldItem
|
|
|
|
|
|
|
|
|
|
|
|
//TODO CHnage this if we ever put NPc city npcs in buildings.
|
|
|
|
//TODO CHnage this if we ever put NPc city npcs in buildings.
|
|
|
|
|
|
|
|
|
|
|
|
int cost = buy.getMagicValue(); |
|
|
|
int cost = buy.getMagicValue(); |
|
|
|
cost *= npc.getSellPercent(sourcePlayer); |
|
|
|
cost *= npc.getSellPercent(sourcePlayer); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (gold.getNumOfItems() - cost < 0) { |
|
|
|
if (gold.getNumOfItems() - cost < 0) { |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128); // Insufficient Gold
|
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 128); // Insufficient Gold
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Building b = (!npc.isStatic()) ? npc.getBuilding() : null; |
|
|
|
Building b = (!npc.isStatic()) ? npc.getBuilding() : null; |
|
|
|
|
|
|
|
|
|
|
|
if (b != null && b.getProtectionState().equals(ProtectionState.NPC)) |
|
|
|
if (b != null && b.getProtectionState().equals(ProtectionState.NPC)) |
|
|
|
b = null; |
|
|
|
b = null; |
|
|
|
int buildingDeposit = cost; |
|
|
|
int buildingDeposit = cost; |
|
|
|
|
|
|
|
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold() && !b.isOwnerIsNPC()) { |
|
|
|
if (b != null && (b.getStrongboxValue() + buildingDeposit) > b.getMaxGold()) { |
|
|
|
|
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206); |
|
|
|
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 206); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) |
|
|
|
if (!itemMan.buyFromNPC(b, cost, buildingDeposit)) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (buy != null) |
|
|
|
if (buy != null) |
|
|
|
itemMan.buyFromNPC(buy, npc); |
|
|
|
itemMan.buyFromNPC(buy, npc); |
|
|
|
|
|
|
|
|
|
|
|
} else |
|
|
|
} else |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (buy != null) { |
|
|
|
if (buy != null) { |
|
|
|
|
|
|
|
|
|
|
|
msg.setItem(buy); |
|
|
|
msg.setItem(buy); |
|
|
|
//send the buy message back to update player
|
|
|
|
//send the buy message back to update player
|
|
|
|
// msg.setItemType(buy.getObjectType().ordinal());
|
|
|
|
// msg.setItemType(buy.getObjectType().ordinal());
|
|
|
@ -1600,14 +1539,43 @@ public class ClientMessagePump implements NetMsgHandler { |
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); |
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); |
|
|
|
itemMan.updateInventory(); |
|
|
|
itemMan.updateInventory(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} finally { |
|
|
|
} finally { |
|
|
|
origin.buyLock.unlock(); |
|
|
|
origin.buyLock.unlock(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
ErrorPopupMsg.sendErrorPopup(origin.getPlayerCharacter(), 12); // All production slots taken
|
|
|
|
ErrorPopupMsg.sendErrorPopup(origin.getPlayerCharacter(), 12); // All production slots taken
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static void handleResourcePurchase(MobEquipment me, CharacterItemManager itemMan, NPC npc, Item buy, PlayerCharacter sourcePlayer, ItemBase ib){ |
|
|
|
|
|
|
|
boolean stacked = false; |
|
|
|
|
|
|
|
int buystack = Warehouse.getSellStackSize(me.getItemBase().getUUID()); |
|
|
|
|
|
|
|
for(Item item : itemMan.getInventory()){ |
|
|
|
|
|
|
|
int itemID = item.getItemBaseID(); |
|
|
|
|
|
|
|
int meID = me.getItemBase().getUUID(); |
|
|
|
|
|
|
|
if(itemID == meID){ |
|
|
|
|
|
|
|
if(Warehouse.maxResources.isEmpty()) |
|
|
|
|
|
|
|
Warehouse.getMaxResources(); |
|
|
|
|
|
|
|
int maxStack = Warehouse.maxResources.get(itemID); |
|
|
|
|
|
|
|
if(maxStack > item.getNumOfItems() + buystack){ |
|
|
|
|
|
|
|
item.setNumOfItems(item.getNumOfItems() + buystack); |
|
|
|
|
|
|
|
stacked = true; |
|
|
|
|
|
|
|
itemMan.updateInventory(); |
|
|
|
|
|
|
|
DbManager.ItemQueries.UPDATE_NUM_ITEMS(item,item.getNumOfItems()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(!stacked){ |
|
|
|
|
|
|
|
buy = Item.createItemForPlayer(sourcePlayer, ib); |
|
|
|
|
|
|
|
if (buy != null) { |
|
|
|
|
|
|
|
me.transferEnchants(buy); |
|
|
|
|
|
|
|
itemMan.addItemToInventory(buy); |
|
|
|
|
|
|
|
buy.setNumOfItems(buystack); |
|
|
|
|
|
|
|
DbManager.ItemQueries.UPDATE_NUM_ITEMS(buy,buy.getNumOfItems()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
itemMan.updateInventory(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void Repair(RepairMsg msg, ClientConnection origin) { |
|
|
|
private static void Repair(RepairMsg msg, ClientConnection origin) { |
|
|
|