forked from MagicBane/Server
New Handler created for SELLOBJECT
This commit is contained in:
@@ -12,7 +12,6 @@ package engine.net.client;
|
|||||||
import engine.Enum.DispatchChannel;
|
import engine.Enum.DispatchChannel;
|
||||||
import engine.Enum.GameObjectType;
|
import engine.Enum.GameObjectType;
|
||||||
import engine.Enum.ItemContainerType;
|
import engine.Enum.ItemContainerType;
|
||||||
import engine.Enum.ProtectionState;
|
|
||||||
import engine.InterestManagement.WorldGrid;
|
import engine.InterestManagement.WorldGrid;
|
||||||
import engine.exception.MsgSendException;
|
import engine.exception.MsgSendException;
|
||||||
import engine.gameManager.*;
|
import engine.gameManager.*;
|
||||||
@@ -36,7 +35,6 @@ import engine.util.StringUtils;
|
|||||||
import org.pmw.tinylog.Logger;
|
import org.pmw.tinylog.Logger;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
@@ -1026,172 +1024,6 @@ public class ClientMessagePump implements NetMsgHandler {
|
|||||||
|
|
||||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void sellToNPC(SellToNPCMsg msg, ClientConnection origin) {
|
|
||||||
|
|
||||||
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
|
||||||
Dispatch dispatch;
|
|
||||||
|
|
||||||
if (player == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CharacterItemManager itemMan = player.charItemManager;
|
|
||||||
|
|
||||||
if (itemMan == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
NPC npc = NPC.getFromCache(msg.getNPCID());
|
|
||||||
|
|
||||||
if (npc == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Item gold = itemMan.getGoldInventory();
|
|
||||||
|
|
||||||
if (gold == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (origin.sellLock.tryLock()) {
|
|
||||||
try {
|
|
||||||
Item sell;
|
|
||||||
int cost = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if (npc.charItemManager.getInventoryCount() > 150) {
|
|
||||||
if (npc.getParentZone() != null && npc.getParentZone().playerCityUUID == 0) {
|
|
||||||
ArrayList<Item> inv = npc.getInventory();
|
|
||||||
for (int i = 0; i < 20; i++) {
|
|
||||||
try {
|
|
||||||
Item toRemove = inv.get(i);
|
|
||||||
if (toRemove != null)
|
|
||||||
npc.charItemManager.delete(toRemove);
|
|
||||||
} catch (Exception e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Early exit sanity check
|
|
||||||
|
|
||||||
if (msg.getItemType() == GameObjectType.Item.ordinal() == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sell = Item.getFromCache(msg.getItemID());
|
|
||||||
|
|
||||||
if (sell == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//get item to sell
|
|
||||||
|
|
||||||
if (sell.template == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (npc.getParentZone() != null && npc.getParentZone().playerCityUUID != 0)
|
|
||||||
if (!npc.charItemManager.hasRoomInventory(sell.template.item_wt)) {
|
|
||||||
|
|
||||||
ErrorPopupMsg.sendErrorPopup(player, 21);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sell.validForInventory(origin, player, itemMan))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//get goldItem cost to sell
|
|
||||||
|
|
||||||
|
|
||||||
cost = sell.template.item_value;
|
|
||||||
|
|
||||||
//apply damaged value reduction
|
|
||||||
float durabilityCurrent = (short) sell.durabilityCurrent;
|
|
||||||
float durabilityMax = sell.template.item_health_full;
|
|
||||||
float damagedModifier = durabilityCurrent / durabilityMax;
|
|
||||||
cost *= damagedModifier;
|
|
||||||
float bargain = player.getBargain();
|
|
||||||
|
|
||||||
float profit = npc.getBuyPercent(player) + bargain;
|
|
||||||
|
|
||||||
if (profit > 1)
|
|
||||||
profit = 1;
|
|
||||||
|
|
||||||
|
|
||||||
cost *= profit;
|
|
||||||
|
|
||||||
if (gold.getNumOfItems() + cost > 10000000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gold.getNumOfItems() + cost < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//TODO make sure npc can buy item type
|
|
||||||
//test room available for item on npc
|
|
||||||
|
|
||||||
// if (!npc.isStatic() && npc.getCharItemManager().getInventoryCount() > 150) {
|
|
||||||
// // chatMan.chatSystemInfo(pc, "This vendor's inventory is full");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//make sure item is in player inventory
|
|
||||||
|
|
||||||
Building building = (!npc.isStatic()) ? npc.getBuilding() : null;
|
|
||||||
|
|
||||||
if (building != null && building.getProtectionState().equals(ProtectionState.NPC))
|
|
||||||
building = null;
|
|
||||||
if (npc.getParentZone().playerCityUUID == 0)
|
|
||||||
building = null;
|
|
||||||
|
|
||||||
//make sure npc can afford item
|
|
||||||
|
|
||||||
if (building != null && !building.hasFunds(cost)) {
|
|
||||||
ErrorPopupMsg.sendErrorPopup(player, 17);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (building != null && (building.getStrongboxValue() - cost) < 0) {
|
|
||||||
ErrorPopupMsg.sendErrorPopup(player, 17);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO transfer item and goldItem transfer should be handled together incase failure
|
|
||||||
//transfer the item
|
|
||||||
|
|
||||||
if (!itemMan.sellToNPC(sell, npc))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!itemMan.sellToNPC(building, cost, sell))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//handle goldItem transfer
|
|
||||||
|
|
||||||
if (sell == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// ***REFACTOR: SellToNpc sends this message, is this a duplicate?
|
|
||||||
|
|
||||||
//update player's goldItem count
|
|
||||||
UpdateGoldMsg ugm = new UpdateGoldMsg(player);
|
|
||||||
ugm.configure();
|
|
||||||
|
|
||||||
dispatch = Dispatch.borrow(player, ugm);
|
|
||||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
||||||
|
|
||||||
//send the sell message back to update player
|
|
||||||
msg.setItemType(sell.getObjectType().ordinal());
|
|
||||||
msg.setItemID(sell.getObjectUUID());
|
|
||||||
msg.setUnknown01(cost); //not sure if this is correct
|
|
||||||
|
|
||||||
dispatch = Dispatch.borrow(player, msg);
|
|
||||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
origin.sellLock.unlock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorPopupMsg.sendErrorPopup(player, 12);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void openBuyFromNPCWindow(BuyFromNPCWindowMsg msg, ClientConnection origin) {
|
private static void openBuyFromNPCWindow(BuyFromNPCWindowMsg msg, ClientConnection origin) {
|
||||||
@@ -1542,9 +1374,6 @@ public class ClientMessagePump implements NetMsgHandler {
|
|||||||
case SHOPINFO:
|
case SHOPINFO:
|
||||||
openSellToNPCWindow((SellToNPCWindowMsg) msg, origin);
|
openSellToNPCWindow((SellToNPCWindowMsg) msg, origin);
|
||||||
break;
|
break;
|
||||||
case SELLOBJECT:
|
|
||||||
sellToNPC((SellToNPCMsg) msg, origin);
|
|
||||||
break;
|
|
||||||
case TRAINERLIST:
|
case TRAINERLIST:
|
||||||
WorldServer.trainerInfo((TrainerInfoMsg) msg, origin);
|
WorldServer.trainerInfo((TrainerInfoMsg) msg, origin);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public enum Protocol {
|
|||||||
SELECTCHAR(0x7E6A9338, GameServerIPRequestMsg.class, null), // Game Server IP Request
|
SELECTCHAR(0x7E6A9338, GameServerIPRequestMsg.class, null), // Game Server IP Request
|
||||||
SELECTCITY(0x7E6BE630, null, null),
|
SELECTCITY(0x7E6BE630, null, null),
|
||||||
SELECTSERVER(0x440D28B7, ServerInfoMsg.class, null), // Server Info Request/Response
|
SELECTSERVER(0x440D28B7, ServerInfoMsg.class, null), // Server Info Request/Response
|
||||||
SELLOBJECT(0x57111C67, SellToNPCMsg.class, null), //Sell to NPC
|
SELLOBJECT(0x57111C67, SellToNPCMsg.class, SellToNPCMsgHandler.class), //Sell to NPC
|
||||||
SENDCITYENTRY(0xBC3B5E72, null, null), //Send Teleport/Repledge List
|
SENDCITYENTRY(0xBC3B5E72, null, null), //Send Teleport/Repledge List
|
||||||
SENDGUILDENTRY(0x6D5EF164, null, null),
|
SENDGUILDENTRY(0x6D5EF164, null, null),
|
||||||
SENDMEMBERENTRY(0x6949C720, GuildListMsg.class, GuildListHandler.class), // ShowCombatInfo guild members list, I think
|
SENDMEMBERENTRY(0x6949C720, GuildListMsg.class, GuildListHandler.class), // ShowCombatInfo guild members list, I think
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||||
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||||
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||||
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||||
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||||
|
// Magicbane Emulator Project © 2013 - 2022
|
||||||
|
// www.magicbane.com
|
||||||
|
|
||||||
|
package engine.net.client.handlers;
|
||||||
|
|
||||||
|
import engine.Enum;
|
||||||
|
import engine.Enum.DispatchChannel;
|
||||||
|
import engine.exception.MsgSendException;
|
||||||
|
import engine.gameManager.SessionManager;
|
||||||
|
import engine.net.Dispatch;
|
||||||
|
import engine.net.DispatchMessage;
|
||||||
|
import engine.net.client.ClientConnection;
|
||||||
|
import engine.net.client.msg.ClientNetMsg;
|
||||||
|
import engine.net.client.msg.ErrorPopupMsg;
|
||||||
|
import engine.net.client.msg.SellToNPCMsg;
|
||||||
|
import engine.net.client.msg.UpdateGoldMsg;
|
||||||
|
import engine.objects.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class SellToNPCMsgHandler extends AbstractClientMsgHandler {
|
||||||
|
|
||||||
|
public SellToNPCMsgHandler() {
|
||||||
|
super(SellToNPCMsg.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||||
|
|
||||||
|
PlayerCharacter pc = origin.getPlayerCharacter();
|
||||||
|
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
||||||
|
Dispatch dispatch;
|
||||||
|
|
||||||
|
if (player == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CharacterItemManager itemMan = player.charItemManager;
|
||||||
|
|
||||||
|
if (itemMan == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
SellToNPCMsg sellToNPCMsg = (SellToNPCMsg) baseMsg;
|
||||||
|
|
||||||
|
NPC npc = NPC.getFromCache(sellToNPCMsg.getNPCID());
|
||||||
|
|
||||||
|
if (npc == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Item gold = itemMan.getGoldInventory();
|
||||||
|
|
||||||
|
if (gold == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (origin.sellLock.tryLock()) {
|
||||||
|
try {
|
||||||
|
Item sell;
|
||||||
|
int cost = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (npc.charItemManager.getInventoryCount() > 150) {
|
||||||
|
if (npc.getParentZone() != null && npc.getParentZone().playerCityUUID == 0) {
|
||||||
|
ArrayList<Item> inv = npc.getInventory();
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
try {
|
||||||
|
Item toRemove = inv.get(i);
|
||||||
|
if (toRemove != null)
|
||||||
|
npc.charItemManager.delete(toRemove);
|
||||||
|
} catch (Exception e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Early exit sanity check
|
||||||
|
|
||||||
|
if (sellToNPCMsg.getItemType() == Enum.GameObjectType.Item.ordinal() == false)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
sell = Item.getFromCache(sellToNPCMsg.getItemID());
|
||||||
|
|
||||||
|
if (sell == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//get item to sell
|
||||||
|
|
||||||
|
if (sell.template == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (npc.getParentZone() != null && npc.getParentZone().playerCityUUID != 0)
|
||||||
|
if (!npc.charItemManager.hasRoomInventory(sell.template.item_wt)) {
|
||||||
|
ErrorPopupMsg.sendErrorPopup(player, 21);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sell.validForInventory(origin, player, itemMan))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//get goldItem cost to sell
|
||||||
|
|
||||||
|
|
||||||
|
cost = sell.template.item_value;
|
||||||
|
|
||||||
|
//apply damaged value reduction
|
||||||
|
float durabilityCurrent = (short) sell.durabilityCurrent;
|
||||||
|
float durabilityMax = sell.template.item_health_full;
|
||||||
|
float damagedModifier = durabilityCurrent / durabilityMax;
|
||||||
|
cost *= damagedModifier;
|
||||||
|
float bargain = player.getBargain();
|
||||||
|
|
||||||
|
float profit = npc.getBuyPercent(player) + bargain;
|
||||||
|
|
||||||
|
if (profit > 1)
|
||||||
|
profit = 1;
|
||||||
|
|
||||||
|
|
||||||
|
cost *= profit;
|
||||||
|
|
||||||
|
if (gold.getNumOfItems() + cost > 10000000)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (gold.getNumOfItems() + cost < 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//TODO make sure npc can buy item type
|
||||||
|
//test room available for item on npc
|
||||||
|
|
||||||
|
// if (!npc.isStatic() && npc.getCharItemManager().getInventoryCount() > 150) {
|
||||||
|
// // chatMan.chatSystemInfo(pc, "This vendor's inventory is full");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//make sure item is in player inventory
|
||||||
|
|
||||||
|
Building building = (!npc.isStatic()) ? npc.getBuilding() : null;
|
||||||
|
|
||||||
|
if (building != null && building.getProtectionState().equals(Enum.ProtectionState.NPC))
|
||||||
|
building = null;
|
||||||
|
|
||||||
|
if (npc.getParentZone().playerCityUUID == 0)
|
||||||
|
building = null;
|
||||||
|
|
||||||
|
//make sure npc can afford item
|
||||||
|
|
||||||
|
if (building != null && !building.hasFunds(cost)) {
|
||||||
|
ErrorPopupMsg.sendErrorPopup(player, 17);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (building != null && (building.getStrongboxValue() - cost) < 0) {
|
||||||
|
ErrorPopupMsg.sendErrorPopup(player, 17);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO transfer item and goldItem transfer should be handled together incase failure
|
||||||
|
//transfer the item
|
||||||
|
|
||||||
|
if (!itemMan.sellToNPC(sell, npc))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!itemMan.sellToNPC(building, cost, sell))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//handle goldItem transfer
|
||||||
|
|
||||||
|
if (sell == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// ***REFACTOR: SellToNpc sends this message, is this a duplicate?
|
||||||
|
|
||||||
|
//update player's goldItem count
|
||||||
|
UpdateGoldMsg ugm = new UpdateGoldMsg(player);
|
||||||
|
ugm.configure();
|
||||||
|
|
||||||
|
dispatch = Dispatch.borrow(player, ugm);
|
||||||
|
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||||
|
|
||||||
|
//send the sell message back to update player
|
||||||
|
sellToNPCMsg.setItemType(sell.getObjectType().ordinal());
|
||||||
|
sellToNPCMsg.setItemID(sell.getObjectUUID());
|
||||||
|
sellToNPCMsg.setUnknown01(cost); //not sure if this is correct
|
||||||
|
|
||||||
|
dispatch = Dispatch.borrow(player, sellToNPCMsg);
|
||||||
|
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
origin.sellLock.unlock();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ErrorPopupMsg.sendErrorPopup(player, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send ping to client
|
||||||
|
|
||||||
|
dispatch = Dispatch.borrow(pc, sellToNPCMsg);
|
||||||
|
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1315,8 +1315,8 @@ public class CharacterItemManager {
|
|||||||
} finally {
|
} finally {
|
||||||
buildingCity.transactionLock.writeLock().unlock();
|
buildingCity.transactionLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} else if (!vendorBuilding.transferGold(buildingDeposit, true))
|
} else
|
||||||
return false;
|
return vendorBuilding.transferGold(buildingDeposit, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1382,8 +1382,10 @@ public class CharacterItemManager {
|
|||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
synchronized (itemMan) {
|
synchronized (itemMan) {
|
||||||
|
|
||||||
if (!this.doesCharOwnThisItem(itemToSell.getObjectUUID()))
|
if (!this.doesCharOwnThisItem(itemToSell.getObjectUUID()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// attempt to transfer item in db
|
// attempt to transfer item in db
|
||||||
|
|
||||||
boolean sdrMerchant = false;
|
boolean sdrMerchant = false;
|
||||||
@@ -1398,13 +1400,14 @@ public class CharacterItemManager {
|
|||||||
} else if (!itemToSell.moveItemToInventory(npc))
|
} else if (!itemToSell.moveItemToInventory(npc))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// db transfer successfull, remove from this character
|
|
||||||
// skip this check if this is a mobLoot item (which is not in any inventory)
|
// skip this check if this is a mobLoot item (which is not in any inventory)
|
||||||
|
|
||||||
if (!sdrMerchant)
|
if (!sdrMerchant)
|
||||||
if (!removeItemFromInventory(itemToSell))
|
if (!removeItemFromInventory(itemToSell))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// add item to looter.
|
// add item to vendor
|
||||||
|
|
||||||
if (!sdrMerchant)
|
if (!sdrMerchant)
|
||||||
if (!itemMan.addItemToInventory(itemToSell))
|
if (!itemMan.addItemToInventory(itemToSell))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user