public abstract class Inventory extends ItemContainer {
public static final int PAPERDOLL_UNDER = 0;
public static final int PAPERDOLL_REAR = 1;
public static final int PAPERDOLL_LEAR = 2;
public static final int PAPERDOLL_NECK = 3;
public static final int PAPERDOLL_RFINGER = 4;
public static final int PAPERDOLL_LFINGER = 5;
public static final int PAPERDOLL_HEAD = 6;
public static final int PAPERDOLL_RHAND = 7;
public static final int PAPERDOLL_LHAND = 8;
public static final int PAPERDOLL_GLOVES = 9;
public static final int PAPERDOLL_CHEST = 10;
public static final int PAPERDOLL_LEGS = 11;
public static final int PAPERDOLL_FEET = 12;
public static final int PAPERDOLL_BACK = 13;
public static final int PAPERDOLL_LRHAND = 14;
public static final int PAPERDOLL_HAIR = 15;
public static final int PAPERDOLL_DHAIR = 16;
public static final int PAPERDOLL_RBRACELET = 17;
public static final int PAPERDOLL_LBRACELET = 18;
public static final int PAPERDOLL_DECO1 = 19;
public static final int PAPERDOLL_DECO2 = 20;
public static final int PAPERDOLL_DECO3 = 21;
public static final int PAPERDOLL_DECO4 = 22;
public static final int PAPERDOLL_DECO5 = 23;
public static final int PAPERDOLL_DECO6 = 24;
public static final int PAPERDOLL_BELT = 25;
public static final int PAPERDOLL_MAX = 26;
public static final int[] PAPERDOLL_ORDER =
{
Inventory.PAPERDOLL_UNDER,
Inventory.PAPERDOLL_REAR,
Inventory.PAPERDOLL_LEAR,
Inventory.PAPERDOLL_NECK,
Inventory.PAPERDOLL_RFINGER,
Inventory.PAPERDOLL_LFINGER,
Inventory.PAPERDOLL_HEAD,
Inventory.PAPERDOLL_RHAND,
Inventory.PAPERDOLL_LHAND,
Inventory.PAPERDOLL_GLOVES,
Inventory.PAPERDOLL_CHEST,
Inventory.PAPERDOLL_LEGS,
Inventory.PAPERDOLL_FEET,
Inventory.PAPERDOLL_BACK,
Inventory.PAPERDOLL_LRHAND,
Inventory.PAPERDOLL_HAIR,
Inventory.PAPERDOLL_DHAIR,
Inventory.PAPERDOLL_RBRACELET,
Inventory.PAPERDOLL_LBRACELET,
Inventory.PAPERDOLL_DECO1,
Inventory.PAPERDOLL_DECO2,
Inventory.PAPERDOLL_DECO3,
Inventory.PAPERDOLL_DECO4,
Inventory.PAPERDOLL_DECO5,
Inventory.PAPERDOLL_DECO6,
Inventory.PAPERDOLL_BELT // Пояс
};
private static final Logger _log = LoggerFactory.getLogger(Inventory.class);
protected final int _ownerId;
protected final ItemInstance[] _paperdoll = new ItemInstance[PAPERDOLL_MAX];
protected final InventoryListenerList _listeners = new InventoryListenerList();
protected int _totalWeight;
// used to quickly check for using of items of special type
protected long _wearedMask;
protected Inventory(int ownerId) {
_ownerId = ownerId;
addListener(StatsListener.getInstance());
}
public static int getPaperdollIndex(int slot) {
switch (slot) {
case ItemTemplate.SLOT_UNDERWEAR:
return PAPERDOLL_UNDER;
case ItemTemplate.SLOT_R_EAR:
return PAPERDOLL_REAR;
case ItemTemplate.SLOT_L_EAR:
return PAPERDOLL_LEAR;
case ItemTemplate.SLOT_NECK:
return PAPERDOLL_NECK;
case ItemTemplate.SLOT_R_FINGER:
return PAPERDOLL_RFINGER;
case ItemTemplate.SLOT_L_FINGER:
return PAPERDOLL_LFINGER;
case ItemTemplate.SLOT_HEAD:
return PAPERDOLL_HEAD;
case ItemTemplate.SLOT_R_HAND:
return PAPERDOLL_RHAND;
case ItemTemplate.SLOT_L_HAND:
return PAPERDOLL_LHAND;
case ItemTemplate.SLOT_LR_HAND:
return PAPERDOLL_LRHAND;
case ItemTemplate.SLOT_GLOVES:
return PAPERDOLL_GLOVES;
case ItemTemplate.SLOT_CHEST:
case ItemTemplate.SLOT_FULL_ARMOR:
case ItemTemplate.SLOT_FORMAL_WEAR:
return PAPERDOLL_CHEST;
case ItemTemplate.SLOT_LEGS:
return PAPERDOLL_LEGS;
case ItemTemplate.SLOT_FEET:
return PAPERDOLL_FEET;
case ItemTemplate.SLOT_BACK:
return PAPERDOLL_BACK;
case ItemTemplate.SLOT_HAIR:
case ItemTemplate.SLOT_HAIRALL:
return PAPERDOLL_HAIR;
case ItemTemplate.SLOT_DHAIR:
return PAPERDOLL_DHAIR;
case ItemTemplate.SLOT_R_BRACELET:
return PAPERDOLL_RBRACELET;
case ItemTemplate.SLOT_L_BRACELET:
return PAPERDOLL_LBRACELET;
case ItemTemplate.SLOT_DECO:
return PAPERDOLL_DECO1; //return first we deal with it later
case ItemTemplate.SLOT_BELT:
return PAPERDOLL_BELT;
}
return -1;
}
public abstract Playable getActor();
protected abstract ItemLocation getBaseLocation();
protected abstract ItemLocation getEquipLocation();
public int getOwnerId() {
return _ownerId;
}
protected void onRestoreItem(ItemInstance item) {
_totalWeight += item.getTemplate().getWeight() * item.getCount();
}
@Override
protected void onAddItem(ItemInstance item) {
item.setOwnerId(getOwnerId());
item.setLocation(getBaseLocation());
item.setLocData(findSlot());
if (item.getJdbcState().isSavable()) {
item.save();
} else {
item.setJdbcState(JdbcEntityState.UPDATED);
item.update();
}
sendAddItem(item);
refreshWeight();
}
@Override
protected void onModifyItem(ItemInstance item) {
item.setJdbcState(JdbcEntityState.UPDATED);
item.update();
sendModifyItem(item);
refreshWeight();
}
@Override
protected void onRemoveItem(ItemInstance item) {
if (item.isEquipped()) {
unEquipItem(item);
}
sendRemoveItem(item);
item.setLocData(-1);
refreshWeight();
}
@Override
protected void onDestroyItem(ItemInstance item) {
item.setCount(0L);
item.delete();
}
protected void onEquip(int slot, ItemInstance item) {
_listeners.onEquip(slot, item);
item.setLocation(getEquipLocation());
item.setLocData(slot);
item.setEquipped(true);
item.setJdbcState(JdbcEntityState.UPDATED);
sendModifyItem(item);
_wearedMask |= item.getTemplate().getItemMask();
}
protected void onUnequip(int slot, ItemInstance item) {
item.setLocation(getBaseLocation());
item.setLocData(findSlot());
item.setEquipped(false);
item.setJdbcState(JdbcEntityState.UPDATED);
item.setChargedSpiritshot(ItemInstance.CHARGED_NONE);
item.setChargedSoulshot(ItemInstance.CHARGED_NONE);
sendModifyItem(item);
_wearedMask &= ~item.getTemplate().getItemMask();
_listeners.onUnequip(slot, item);
}
/**
* Находит и возвращает пустой слот в инвентаре.
*/
private int findSlot() {
int slot = 0;
loop:
for (slot = 0; slot < _items.size(); slot++) {
for (ItemInstance item : _items) {
if (item.isEquipped() || item.getTemplate().isQuest()) // игнорируем надетое и квестовые вещи
continue;
if (item.getEquipSlot() == slot) // слот занят?
continue loop;
}
break;
}
return slot; // слот не занят, возвращаем
}
public ItemInstance getPaperdollItem(int slot) {
return _paperdoll[slot];
}
public ItemInstance[] getPaperdollItems() {
return _paperdoll;
}
public int getPaperdollItemId(int slot) {
ItemInstance item = getPaperdollItem(slot);
if (item == null) {
if (slot == PAPERDOLL_HAIR) {
item = _paperdoll[PAPERDOLL_DHAIR];
if (item != null)
return item.getItemId();
else
return 0;
} else {
return 0;
}
}
if (getActor() != null && getActor().getPlayer() != null && !getActor().getPlayer().isInOlympiadMode()) {
ItemInstance chest = getPaperdollItem(PAPERDOLL_CHEST);
if (getActor().getPlayer().isInLastHero() && EventsConfig.LhVisualItems.containsKey(slot))
return EventsConfig.LhVisualItems.get(slot);
if (chest != null && chest.isVisualItem() && VisualUtils.isCostume(chest)) {
switch (slot) {
case PAPERDOLL_CHEST:
return chest.getVisualItemId();
case PAPERDOLL_LEGS:
case PAPERDOLL_FEET:
case PAPERDOLL_GLOVES:
return 0;
}
}
return item.isVisualItem() ? item.getVisualItemId() : item.getItemId();
} else {
return item.getItemId();
}
}
public int getPaperdollVisualItemId(int slot) {
ItemInstance item = getPaperdollItem(slot);
if (item != null) {
if (slot == PAPERDOLL_LEGS || slot == PAPERDOLL_HEAD || slot == PAPERDOLL_FEET || slot == PAPERDOLL_GLOVES) {
ItemInstance paperdollItem = getPaperdollItem(PAPERDOLL_CHEST);
if (paperdollItem != null && (paperdollItem.getCustomFlags() & ItemInstance.FLAG_COSTUME) == ItemInstance.FLAG_COSTUME)
return 0;
}
int visualItemId = item.getVisualItemId();
if (visualItemId != 0)
return visualItemId;
else
return item.getItemId();
} else if (slot == PAPERDOLL_HAIR) {
item = _paperdoll[PAPERDOLL_DHAIR];
if (item != null)
return item.getItemId();
}
return 0;
}
public int getPaperdollObjectId(int slot) {
ItemInstance item = _paperdoll[slot];
if (item != null) {
return item.getObjectId();
} else if (slot == PAPERDOLL_HAIR) {
item = _paperdoll[PAPERDOLL_DHAIR];
if (item != null) {
return item.getObjectId();
}
}
return 0;
}
public void addListener(OnEquipListener listener) {
_listeners.add(listener);
}
public void removeListener(OnEquipListener listener) {
_listeners.remove(listener);
}
public ItemInstance setPaperdollItem(int slot, ItemInstance item) {
ItemInstance old;
writeLock();
try {
old = _paperdoll[slot];
if (old != item) {
if (old != null) {
_paperdoll[slot] = null;
onUnequip(slot, old);
}
if (item != null) {
_paperdoll[slot] = item;
onEquip(slot, item);
}
}
} finally {
writeUnlock();
}
return old;
}
public long getWearedMask() {
return _wearedMask;
}
public void unEquipItem(ItemInstance item) {
if (item.isEquipped()) {
unEquipItemInBodySlot(item.getBodyPart(), item);
}
}
public void unEquipItemInBodySlot(int bodySlot) {
unEquipItemInBodySlot(bodySlot, null);
}
private void unEquipItemInBodySlot(int bodySlot, ItemInstance item) {
int pdollSlot = -1;
switch (bodySlot) {
case ItemTemplate.SLOT_NECK:
pdollSlot = PAPERDOLL_NECK;
break;
case ItemTemplate.SLOT_L_EAR:
pdollSlot = PAPERDOLL_LEAR;
break;
case ItemTemplate.SLOT_R_EAR:
pdollSlot = PAPERDOLL_REAR;
break;
case ItemTemplate.SLOT_L_EAR | ItemTemplate.SLOT_R_EAR:
if (item == null) {
return;
}
if (getPaperdollItem(PAPERDOLL_LEAR) == item) {
pdollSlot = PAPERDOLL_LEAR;
}
if (getPaperdollItem(PAPERDOLL_REAR) == item) {
pdollSlot = PAPERDOLL_REAR;
}
break;
case ItemTemplate.SLOT_L_FINGER:
pdollSlot = PAPERDOLL_LFINGER;
break;
case ItemTemplate.SLOT_R_FINGER:
pdollSlot = PAPERDOLL_RFINGER;
break;
case ItemTemplate.SLOT_L_FINGER | ItemTemplate.SLOT_R_FINGER:
if (item == null) {
return;
}
if (getPaperdollItem(PAPERDOLL_LFINGER) == item) {
pdollSlot = PAPERDOLL_LFINGER;
}
if (getPaperdollItem(PAPERDOLL_RFINGER) == item) {
pdollSlot = PAPERDOLL_RFINGER;
}
break;
case ItemTemplate.SLOT_HAIR:
pdollSlot = PAPERDOLL_HAIR;
break;
case ItemTemplate.SLOT_DHAIR:
pdollSlot = PAPERDOLL_DHAIR;
break;
case ItemTemplate.SLOT_HAIRALL:
setPaperdollItem(PAPERDOLL_DHAIR, null); // This should be the same as in DHAIR
pdollSlot = PAPERDOLL_HAIR;
break;
case ItemTemplate.SLOT_HEAD:
pdollSlot = PAPERDOLL_HEAD;
break;
case ItemTemplate.SLOT_R_HAND:
pdollSlot = PAPERDOLL_RHAND;
break;
case ItemTemplate.SLOT_L_HAND:
pdollSlot = PAPERDOLL_LHAND;
break;
case ItemTemplate.SLOT_GLOVES:
pdollSlot = PAPERDOLL_GLOVES;
break;
case ItemTemplate.SLOT_LEGS:
pdollSlot = PAPERDOLL_LEGS;
break;
case ItemTemplate.SLOT_CHEST:
case ItemTemplate.SLOT_FULL_ARMOR:
case ItemTemplate.SLOT_FORMAL_WEAR:
pdollSlot = PAPERDOLL_CHEST;
break;
case ItemTemplate.SLOT_BACK:
pdollSlot = PAPERDOLL_BACK;
break;
case ItemTemplate.SLOT_FEET:
pdollSlot = PAPERDOLL_FEET;
break;
case ItemTemplate.SLOT_UNDERWEAR:
pdollSlot = PAPERDOLL_UNDER;
break;
case ItemTemplate.SLOT_BELT:
pdollSlot = PAPERDOLL_BELT;
break;
case ItemTemplate.SLOT_LR_HAND:
setPaperdollItem(PAPERDOLL_LHAND, null);
pdollSlot = PAPERDOLL_RHAND;
break;
case ItemTemplate.SLOT_L_BRACELET:
pdollSlot = PAPERDOLL_LBRACELET;
break;
case ItemTemplate.SLOT_R_BRACELET:
pdollSlot = PAPERDOLL_RBRACELET;
// При снятии правого браслета, снимаем и талисманы тоже
setPaperdollItem(Inventory.PAPERDOLL_DECO1, null);
setPaperdollItem(Inventory.PAPERDOLL_DECO2, null);
setPaperdollItem(Inventory.PAPERDOLL_DECO3, null);
setPaperdollItem(Inventory.PAPERDOLL_DECO4, null);
setPaperdollItem(Inventory.PAPERDOLL_DECO5, null);
setPaperdollItem(Inventory.PAPERDOLL_DECO6, null);
break;
case ItemTemplate.SLOT_DECO:
if (item == null) {
return;
} else if (getPaperdollItem(PAPERDOLL_DECO1) == item) {
pdollSlot = PAPERDOLL_DECO1;
} else if (getPaperdollItem(PAPERDOLL_DECO2) == item) {
pdollSlot = PAPERDOLL_DECO2;
} else if (getPaperdollItem(PAPERDOLL_DECO3) == item) {
pdollSlot = PAPERDOLL_DECO3;
} else if (getPaperdollItem(PAPERDOLL_DECO4) == item) {
pdollSlot = PAPERDOLL_DECO4;
} else if (getPaperdollItem(PAPERDOLL_DECO5) == item) {
pdollSlot = PAPERDOLL_DECO5;
} else if (getPaperdollItem(PAPERDOLL_DECO6) == item) {
pdollSlot = PAPERDOLL_DECO6;
}
break;
default:
_log.warn("Requested invalid body slot: " + bodySlot + ", Item: " + item + ", ownerId: '" + getOwnerId() + '\'');
return;
}
if (pdollSlot >= 0) {
setPaperdollItem(pdollSlot, null);
}
}
public void equipItem(ItemInstance item) {
int bodySlot = item.getBodyPart();
//TODO [G1ta0] затычка на статы повышающие HP/MP/CP
double hp = getActor().getCurrentHp();
double mp = getActor().getCurrentMp();
double cp = getActor().getCurrentCp();
switch (bodySlot) {
case ItemTemplate.SLOT_LR_HAND: {
setPaperdollItem(PAPERDOLL_LHAND, null);
setPaperdollItem(PAPERDOLL_RHAND, item);
break;
}
case ItemTemplate.SLOT_L_HAND: {
final ItemInstance rHandItem = getPaperdollItem(PAPERDOLL_RHAND);
final ItemTemplate rHandItemTemplate = rHandItem == null ? null : rHandItem.getTemplate();
final ItemTemplate newItem = item.getTemplate();
if (newItem.getItemType() == EtcItemType.ARROW) {
// arrows can be equipped only with bow
if (rHandItemTemplate == null) {
return;
}
if (rHandItemTemplate.getItemType() != WeaponType.BOW) {
return;
}
if (rHandItemTemplate.getCrystalType() != newItem.getCrystalType()) {
return;
}
} else if (newItem.getItemType() == EtcItemType.BOLT) {
// bolts can be equipped only with crossbow
if (rHandItemTemplate == null) {
return;
}
if (rHandItemTemplate.getItemType() != WeaponType.CROSSBOW) {
return;
}
if (rHandItemTemplate.getCrystalType() != newItem.getCrystalType()) {
return;
}
} else if (newItem.getItemType() == EtcItemType.BAIT) {
// baits can be equipped only with rods
if (rHandItemTemplate == null) {
return;
}
if (rHandItemTemplate.getItemType() != WeaponType.ROD) {
return;
}
if (!getActor().isPlayer()) {
return;
}
Player owner = (Player) getActor();
owner.getPlayerVariables().set(PlayerVariables.LAST_LURE, String.valueOf(item.getObjectId()), -1);
} else {
// unequip two-hand weapon
if (rHandItemTemplate != null && rHandItemTemplate.getBodyPart() == ItemTemplate.SLOT_LR_HAND) {
setPaperdollItem(PAPERDOLL_RHAND, null);
}
}
setPaperdollItem(PAPERDOLL_LHAND, item);
break;
}
case ItemTemplate.SLOT_R_HAND: {
setPaperdollItem(PAPERDOLL_RHAND, item);
break;
}
case ItemTemplate.SLOT_L_EAR:
case ItemTemplate.SLOT_R_EAR:
case ItemTemplate.SLOT_L_EAR | ItemTemplate.SLOT_R_EAR: {
if (_paperdoll[PAPERDOLL_REAR] == null) {
setPaperdollItem(PAPERDOLL_REAR, item);
} else if (_paperdoll[PAPERDOLL_LEAR] == null) {
setPaperdollItem(PAPERDOLL_LEAR, item);
} else {
setPaperdollItem(PAPERDOLL_REAR, item);
}
break;
}
case ItemTemplate.SLOT_L_FINGER:
case ItemTemplate.SLOT_R_FINGER:
case ItemTemplate.SLOT_L_FINGER | ItemTemplate.SLOT_R_FINGER: {
if (_paperdoll[PAPERDOLL_RFINGER] == null) {
setPaperdollItem(PAPERDOLL_RFINGER, item);
} else if (_paperdoll[PAPERDOLL_LFINGER] == null) {
setPaperdollItem(PAPERDOLL_LFINGER, item);
} else {
setPaperdollItem(PAPERDOLL_RFINGER, item);
}
break;
}
case ItemTemplate.SLOT_NECK:
setPaperdollItem(PAPERDOLL_NECK, item);
break;
case ItemTemplate.SLOT_FULL_ARMOR:
setPaperdollItem(PAPERDOLL_LEGS, null);
setPaperdollItem(PAPERDOLL_CHEST, item);
break;
case ItemTemplate.SLOT_CHEST:
setPaperdollItem(PAPERDOLL_CHEST, item);
break;
case ItemTemplate.SLOT_LEGS: {
// handle full armor
ItemInstance chest = getPaperdollItem(PAPERDOLL_CHEST);
if (chest != null && chest.getBodyPart() == ItemTemplate.SLOT_FULL_ARMOR) {
setPaperdollItem(PAPERDOLL_CHEST, null);
} else if (getPaperdollItemId(PAPERDOLL_CHEST) == ItemTemplate.ITEM_ID_FORMAL_WEAR) {
setPaperdollItem(PAPERDOLL_CHEST, null);
}
setPaperdollItem(PAPERDOLL_LEGS, item);
break;
}
case ItemTemplate.SLOT_FEET:
if (getPaperdollItemId(PAPERDOLL_CHEST) == ItemTemplate.ITEM_ID_FORMAL_WEAR) {
setPaperdollItem(PAPERDOLL_CHEST, null);
}
setPaperdollItem(PAPERDOLL_FEET, item);
break;
case ItemTemplate.SLOT_GLOVES:
if (getPaperdollItemId(PAPERDOLL_CHEST) == ItemTemplate.ITEM_ID_FORMAL_WEAR) {
setPaperdollItem(PAPERDOLL_CHEST, null);
}
setPaperdollItem(PAPERDOLL_GLOVES, item);
break;
case ItemTemplate.SLOT_HEAD:
if (getPaperdollItemId(PAPERDOLL_CHEST) == ItemTemplate.ITEM_ID_FORMAL_WEAR) {
setPaperdollItem(PAPERDOLL_CHEST, null);
}
setPaperdollItem(PAPERDOLL_HEAD, item);
break;
case ItemTemplate.SLOT_HAIR:
ItemInstance old = getPaperdollItem(PAPERDOLL_DHAIR);
if (old != null && old.getBodyPart() == ItemTemplate.SLOT_HAIRALL) {
setPaperdollItem(PAPERDOLL_DHAIR, null);
}
setPaperdollItem(PAPERDOLL_HAIR, item);
break;
case ItemTemplate.SLOT_DHAIR:
ItemInstance slot2 = getPaperdollItem(PAPERDOLL_DHAIR);
if (slot2 != null && slot2.getBodyPart() == ItemTemplate.SLOT_HAIRALL) {
setPaperdollItem(PAPERDOLL_HAIR, null);
}
setPaperdollItem(PAPERDOLL_DHAIR, item);
break;
case ItemTemplate.SLOT_HAIRALL:
setPaperdollItem(PAPERDOLL_HAIR, null);
setPaperdollItem(PAPERDOLL_DHAIR, item);
break;
case ItemTemplate.SLOT_R_BRACELET:
setPaperdollItem(PAPERDOLL_RBRACELET, item);
break;
case ItemTemplate.SLOT_L_BRACELET:
setPaperdollItem(PAPERDOLL_LBRACELET, item);
break;
case ItemTemplate.SLOT_UNDERWEAR:
setPaperdollItem(PAPERDOLL_UNDER, item);
break;
case ItemTemplate.SLOT_BACK:
setPaperdollItem(PAPERDOLL_BACK, item);
break;
case ItemTemplate.SLOT_BELT:
setPaperdollItem(PAPERDOLL_BELT, item);
break;
case ItemTemplate.SLOT_DECO:
if (_paperdoll[PAPERDOLL_DECO1] == null) {
setPaperdollItem(PAPERDOLL_DECO1, item);
} else if (_paperdoll[PAPERDOLL_DECO2] == null) {
setPaperdollItem(PAPERDOLL_DECO2, item);
} else if (_paperdoll[PAPERDOLL_DECO3] == null) {
setPaperdollItem(PAPERDOLL_DECO3, item);
} else if (_paperdoll[PAPERDOLL_DECO4] == null) {
setPaperdollItem(PAPERDOLL_DECO4, item);
} else if (_paperdoll[PAPERDOLL_DECO5] == null) {
setPaperdollItem(PAPERDOLL_DECO5, item);
} else if (_paperdoll[PAPERDOLL_DECO6] == null) {
setPaperdollItem(PAPERDOLL_DECO6, item);
} else {
setPaperdollItem(PAPERDOLL_DECO1, item);
}
break;
case ItemTemplate.SLOT_FORMAL_WEAR:
// При одевании свадебного платья руки не трогаем
setPaperdollItem(PAPERDOLL_LEGS, null);
setPaperdollItem(PAPERDOLL_HEAD, null);
setPaperdollItem(PAPERDOLL_FEET, null);
setPaperdollItem(PAPERDOLL_GLOVES, null);
setPaperdollItem(PAPERDOLL_CHEST, item);
break;
default:
_log.warn("unknown body slot:" + bodySlot + " for item id: " + item.getItemId());
return;
}
//TODO [G1ta0] затычка на статы повышающие HP/MP/CP
getActor().setCurrentHp(hp, false);
getActor().setCurrentMp(mp);
getActor().setCurrentCp(cp);
if (getActor().isPlayer()) {
((Player) getActor()).autoShot();
}
}
protected abstract void sendAddItem(ItemInstance item);
protected abstract void sendModifyItem(ItemInstance item);
protected abstract void sendRemoveItem(ItemInstance item);
/**
* Refresh the weight of equipment loaded
*/
protected void refreshWeight() {
int weight = 0;
readLock();
try {
for (ItemInstance item : _items)
weight += item.getTemplate().getWeight() * item.getCount();
} finally {
readUnlock();
}
if (_totalWeight == weight) {
return;
}
_totalWeight = weight;
onRefreshWeight();
}
protected abstract void onRefreshWeight();
public int getTotalWeight() {
return _totalWeight;
}
public boolean validateCapacity(ItemInstance item) {
long slots = 0;
if (!item.isStackable() || getItemByItemId(item.getItemId()) == null) {
slots++;
}
return validateCapacity(slots);
}
public boolean validateCapacity(int itemId, long count) {
ItemTemplate item = ItemTemplateHolder.getInstance().getTemplate(itemId);
return validateCapacity(item, count);
}
public boolean validateCapacity(ItemTemplate item, long count) {
long slots = 0;
if (!item.isStackable() || getItemByItemId(item.getItemId()) == null) {
slots = count;
}
return validateCapacity(slots);
}
public boolean validateCapacity(long slots) {
if (slots == 0) {
return true;
}
if (slots < Integer.MIN_VALUE || slots > Integer.MAX_VALUE) {
return false;
}
if (getSize() + (int) slots < 0) {
return false;
}
return getSize() + slots <= getActor().getInventoryLimit();
}
public boolean validateWeight(ItemInstance item) {
long weight = item.getTemplate().getWeight() * item.getCount();
return validateWeight(weight);
}
public boolean validateWeight(int itemId, long count) {
ItemTemplate item = ItemTemplateHolder.getInstance().getTemplate(itemId);
return validateWeight(item, count);
}
public boolean validateWeight(ItemTemplate item, long count) {
long weight = item.getWeight() * count;
return validateWeight(weight);
}
public boolean validateWeight(long weight) {
if (weight == 0L) {
return true;
}
if (weight < Integer.MIN_VALUE || weight > Integer.MAX_VALUE) {
return false;
}
if (getTotalWeight() + (int) weight < 0) {
return false;
}
return getTotalWeight() + weight <= getActor().getMaxLoad();
}
public abstract void restore();
public abstract void store();
@Override
public int getSize() {
return super.getSize() - getQuestSize();
}
public int getAllSize() {
return super.getSize();
}
public int getQuestSize() {
int size = 0;
for (ItemInstance item : getItems()) {
if (item.getTemplate().isQuest()) {
size++;
}
}
return size;
}
public static class ItemOrderComparator implements Comparator<ItemInstance> {
private static final Comparator<ItemInstance> instance = new ItemOrderComparator();
public static Comparator<ItemInstance> getInstance() {
return instance;
}
@Override
public int compare(ItemInstance o1, ItemInstance o2) {
if (o1 == null || o2 == null) {
return 0;
}
return o1.getLocData() - o2.getLocData();
}
}
public class InventoryListenerList extends ListenerList<Playable> {
public void onEquip(int slot, ItemInstance item) {
for (OnEquipListener listener : getListeners(OnEquipListener.class))
listener.onEquip(slot, item, getActor());
}
public void onUnequip(int slot, ItemInstance item) {
for (OnEquipListener listener : getListeners(OnEquipListener.class))
listener.onUnequip(slot, item, getActor());
}
}
}
Да, любой шмот можно было. Как повторить помню, но описывать лень)Году в 12 брали исходы овероподобные, там был этот баг, как фиксили и как повторить баг не помню, но точно помню что можно было как то запихать 2 пухи в 1 слот или бижутерию ну и тд.
Ну так пацаны поддержат . Сливай старую багулю под хайдДа, любой шмот можно было. Как повторить помню, но описывать лень)
По идее да.А именно из-за передачи предметов это?
Или были дополнительные действия? Похож на баг с трейдом при пвп + саб.
смотрел в ту же сторону и вроде там все ок.Логика снял\одел в setPaperdollItem вроде правильная
Единственное чего я не вижу это сохранения состояния предмета в базу после вызова onEquip(...) и onUnequip(...) - там какойнибудь item.save() или item.update().
Вижу что он есть в onModifyItem(...) и возможно он дальше где-то дергается листенерами, но уже непомню как там должно быть в оверах
Посмотрите в этом направлении, может что-то меняли и провтыкали сохранение.
Самый простой способ отключи setNextIntention() при экипировке, принудительно менять экипировку а не ждать пока персонаж освободится или в tradedone добавить проверку если передаваемый obj в очереди давать фейл, смотри setNextIntention() в связке со скиллами при action сидеть, вставать похожий метод бага если у тебя есть свап Саба через кб, при баге итемов через пета во время релога на jts вылетал краш клиентаПо идее да.
Дополню. В базе все как я описал, но каждый раз когда чел заходит повторяет те же действия с трейдом, а если я зайду на персонажа пока в базе весит этот набор из PAPERDOLL то при логине персонаж со своими нормальными статами а в базе все становится в порядке. Тоесть выходит до релога эти статы, и как они появляются в базе тоже не понял, так как я воспроизвести не смог, возможно как то при автосохранении чара, но это лишь догадка, там тоже прошелся ничего не увидел, и как писал
смотрел в ту же сторону и вроде там все ок.
И я не менял ничего в скриптах связанных с трейдом или инвентарем.
Вот как это выглядит в логах
2023-09-07 17:34:06,295 DEBUG o.m.g.u.Log [ThreadPoolExecutor-4] - TradeSell 11855 Common Item - Demon's Staff (1)[257321] Char_A[60854] 1
2023-09-07 17:34:06,295 DEBUG o.m.g.u.Log [ThreadPoolExecutor-4] - TradeBuy 11855 Common Item - Demon's Staff (1)[257321] Char_B[259462] 1
2023-09-07 17:34:06,298 DEBUG o.m.g.u.Log [ThreadPoolExecutor-4] - TradeSell 11855 Common Item - Demon's Staff (1)[257322] Char_A[60854] 1
2023-09-07 17:34:06,298 DEBUG o.m.g.u.Log [ThreadPoolExecutor-4] - TradeBuy 11855 Common Item - Demon's Staff (1)[257322] Char_B[259462] 1
2023-09-07 17:34:06,300 DEBUG o.m.g.u.Log [ThreadPoolExecutor-4] - TradeSell 11855 Common Item - Demon's Staff (1)[257323] Char_A[60854] 1
2023-09-07 17:34:06,300 DEBUG o.m.g.u.Log [ThreadPoolExecutor-4] - TradeBuy 11855 Common Item - Demon's Staff (1)[257323] Char_B[259462] 1
2023-09-07 17:34:46,234 DEBUG o.m.g.u.Log [ThreadPoolExecutor-1] - TradeSell 11855 Common Item - Demon's Staff (1)[257319] Char_B[259462] 1
2023-09-07 17:34:46,234 DEBUG o.m.g.u.Log [ThreadPoolExecutor-1] - TradeBuy 11855 Common Item - Demon's Staff (1)[257319] Char_A[60854] 1
2023-09-07 17:35:07,622 DEBUG o.m.g.u.Log [ThreadPoolExecutor-3] - TradeSell 11855 Common Item - Demon's Staff (1)[257324] Char_B[259462] 1
2023-09-07 17:35:07,622 DEBUG o.m.g.u.Log [ThreadPoolExecutor-3] - TradeBuy 11855 Common Item - Demon's Staff (1)[257324] Char_A[60854] 1
2023-09-07 17:35:37,931 DEBUG o.m.g.u.Log [ThreadPoolExecutor-3] - TradeSell 11855 Common Item - Demon's Staff (1)[257326] Char_B[259462] 1
2023-09-07 17:35:37,931 DEBUG o.m.g.u.Log [ThreadPoolExecutor-3] - TradeBuy 11855 Common Item - Demon's Staff (1)[257326] Char_A[60854] 1
и так далее...
Дополню, не успел отредактировать прошлый
В конце делает
2023-09-07 17:40:47,606 DEBUG o.m.g.u.Log [ThreadPoolExecutor-4] - Drop 11855 Common Item - Demon's Staff (1)[257324] Char_A[60854] 1
2023-09-07 17:40:51,463 DEBUG o.m.g.u.Log [ThreadPoolExecutor-1] - Pickup 11855 Common Item - Demon's Staff (1)[257324] Char_B[259462] 1
2023-09-07 17:58:27,686 DEBUG o.m.g.u.Log [ThreadPoolExecutor-3] - TradeSell 11855 Common Item - Demon's Staff (1)[257320] Char_B[259462] 1
2023-09-07 17:58:27,686 DEBUG o.m.g.u.Log [ThreadPoolExecutor-3] - TradeBuy 11855 Common Item - Demon's Staff (1)[257320] Char_A[60854] 1
и идет фармить
case EQUIP:
if(nextAction_arg0 == null || !actor.isPlayer() ||!(nextAction_arg0 instanceof ItemInstance))
return false;
ItemInstance item = (ItemInstance)nextAction_arg0;
item.getTemplate().getHandler().useItem(actor, item, _nextAction_arg2);
break;
Глянул какой-то рандомный овероподобный сорс, в место о котором говорил Gaikotsu и Hibiki
setNextIntention() c EQUIP дергает EquipableItem.useItem для вещей которые можно одеть.
И втеории можно предположить что в этом месте, если начать кастовать скилл, затем отправить в очередь команду на одевание предмента, и дальше этот предмет отправить в трейд то может что-то пойти не так.
Посмотреть вложение 55305
Кажеться здесь какбудто бы не хватает проверки что пердмет еще у персонажа, либо просто перед тем как отправить setNextIntention() c EQUIP проверить есть ли активный трейд и закенселить его
Посмотрите, возможно в JTS тоже самое
case EQUIP:
if (!(nextAction_arg0 instanceof ItemInstance)) {
return false;
}
final ItemInstance item = (ItemInstance) nextAction_arg0;
if (item.isEquipable()) {
item.getTemplate().getHandler().useItem(getActor(), item, nextAction_arg2);
}
clearNextAction();
if (getIntention() == AI_INTENTION_ATTACK) // autoattack not aborted
{
return false;
}
break;
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?