Implement inventory functions

AddItem, RemoveItem, GetItemName, GetItemCount, GetItemHealth, GetInventorySize SendInventory
Example:
```lua
tes3mp.AddItem(pid, "glass dagger", 1, 50)
tes3mp.AddItem(pid, "glass dagger", 1, -1)
tes3mp.SendInventory(pid)
tes3mp.RemoveItem(pid, "glass dagger", 1)
tes3mp.SendInventory(pid)
local invSize = tes3mp.GetInventorySize(pid) - 1
for i = 0, invSize do
    print(("%s %d %d"):format(tes3mp.GetItemName(pid, i), tes3mp.GetItemCount(pid, i), tes3mp.GetItemHealth(pid, i)))
end
```
pull/112/merge
Koncord 8 years ago
parent 81dfd21d9a
commit c27351c19e

@ -371,6 +371,12 @@ void Networking::Update(RakNet::Packet *packet)
myPacket->Read(player);
break;
}
case ID_GAME_INVENTORY:
{
DEBUG_PRINTF("ID_GAME_INVENTORY\n");
myPacket->Read(player);
break;
}
default:
printf("Message with identifier %i has arrived.\n", packet->data[0]);

@ -62,6 +62,8 @@ public:
unsigned short getLastAttackerID();
virtual ~Player();
public:
mwmp::Inventory inventorySendBuffer;
private:
bool handshake;
int loaded;

@ -8,22 +8,30 @@
#include <apps/openmw-mp/Networking.hpp>
#include <components/misc/stringops.hpp>
using namespace mwmp;
void ItemFunctions::AddItem(unsigned short pid, const char* itemName, unsigned short count) noexcept
void ItemFunctions::AddItem(unsigned short pid, const char* itemName, unsigned int count, int health) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
LOG_MESSAGE(Log::LOG_WARN, "%s", "stub");
Item item;
item.refid = itemName;
item.count = count;
item.health = health;
player->inventorySendBuffer.items.push_back(item);
player->inventorySendBuffer.action = Inventory::ADDITEM;
}
void ItemFunctions::EquipItem(unsigned short pid, unsigned short slot, const char *itemName, unsigned short count) noexcept
void ItemFunctions::EquipItem(unsigned short pid, unsigned short slot, const char *itemName, unsigned int count, int health) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->EquipedItem(slot)->refid = itemName;
player->EquipedItem(slot)->count = count;
player->EquipedItem(slot)->health = health;
}
void ItemFunctions::UnequipItem(unsigned short pid, unsigned short slot) noexcept
@ -53,13 +61,54 @@ bool ItemFunctions::HasItemEquipped(unsigned short pid, const char* itemName)
void ItemFunctions::RemoveItem(unsigned short pid, const char* itemName, unsigned short count) noexcept
{
LOG_MESSAGE(Log::LOG_WARN, "%s", "stub");
Player *player;
GET_PLAYER(pid, player,);
Item item;
item.refid = itemName;
item.count = count;
player->inventorySendBuffer.items.clear();
player->inventorySendBuffer.items.push_back(item);
player->inventorySendBuffer.action = Inventory::REMOVEITEM;
}
void ItemFunctions::GetItemCount(unsigned short pid, const char* itemName) noexcept
{
LOG_MESSAGE(Log::LOG_WARN, "%s", "stub");
}
const char *ItemFunctions::GetItemName(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
return player->inventory.items.at(i).refid.c_str();
}
int ItemFunctions::GetItemCount2(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->inventory.items.at(i).count;
}
int ItemFunctions::GetItemHealth(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->inventory.items.at(i).health;
}
unsigned int ItemFunctions::GetInventorySize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->inventory.count;
}
void ItemFunctions::SendEquipment(unsigned short pid) noexcept
{
Player *player;
@ -68,3 +117,13 @@ void ItemFunctions::SendEquipment(unsigned short pid) noexcept
mwmp::Networking::Get().GetController()->GetPacket(ID_GAME_EQUIPMENT)->Send(player, false);
mwmp::Networking::Get().GetController()->GetPacket(ID_GAME_EQUIPMENT)->Send(player, true);
}
void ItemFunctions::SendInventory(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
std::swap(player->inventory, player->inventorySendBuffer);
mwmp::Networking::Get().GetController()->GetPacket(ID_GAME_INVENTORY)->Send(player, false);
player->inventory = std::move(player->inventorySendBuffer);
player->inventorySendBuffer.items.clear();
}

@ -8,27 +8,38 @@
#define ITEMAPI \
{"AddItem", ItemFunctions::AddItem},\
{"RemoveItem", ItemFunctions::RemoveItem},\
{"GetItemCount", ItemFunctions::GetItemCount},\
{"GetItemCount", ItemFunctions::GetItemCount2},\
{"EquipItem", ItemFunctions::EquipItem},\
{"UnequipItem", ItemFunctions::UnequipItem},\
{"GetItemSlot", ItemFunctions::GetItemSlot},\
{"HasItemEquipped", ItemFunctions::HasItemEquipped},\
{"GetItemName", ItemFunctions::GetItemName},\
{"GetItemHealth", ItemFunctions::GetItemHealth},\
{"GetInventorySize", ItemFunctions::GetInventorySize},\
\
{"SendEquipment", ItemFunctions::SendEquipment}\
{"SendEquipment", ItemFunctions::SendEquipment},\
{"SendInventory", ItemFunctions::SendInventory}\
class ItemFunctions
{
public:
static void AddItem(unsigned short pid, const char* itemName, unsigned short count) noexcept;
static void AddItem(unsigned short pid, const char* itemName, unsigned int count, int health) noexcept;
static void RemoveItem(unsigned short pid, const char* itemName, unsigned short count) noexcept;
static void GetItemCount(unsigned short pid, const char* itemName) noexcept;
static void EquipItem(unsigned short pid, unsigned short slot, const char* itemName, unsigned short count) noexcept;
static void EquipItem(unsigned short pid, unsigned short slot, const char* itemName, unsigned int count, int health) noexcept;
static void UnequipItem(unsigned short pid, unsigned short slot) noexcept;
static bool HasItemEquipped(unsigned short pid, const char* itemName);
static const char *GetItemSlot(unsigned short pid, unsigned short slot) noexcept;
static const char *GetItemName(unsigned short pid, unsigned int i) noexcept;
static int GetItemCount2(unsigned short pid, unsigned int i) noexcept;
static int GetItemHealth(unsigned short pid, unsigned int i) noexcept;
static unsigned int GetInventorySize(unsigned short pid) noexcept;
static void SendEquipment(unsigned short pid) noexcept;
static void SendInventory(unsigned short pid) noexcept;
private:
};
#endif //OPENMW_ITEMS_HPP

@ -58,11 +58,12 @@ void LocalPlayer::Update()
updateDrawStateAndFlags();
updateAttackState();
updateDeadState();
updateInventory();
updateEquipped();
updateDynamicStats();
updateAttributes();
updateSkills();
updateLevel();
updateInventory();
}
void LocalPlayer::charGen(int stageFirst, int stageEnd)
@ -355,15 +356,14 @@ void LocalPlayer::updateChar()
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->rebuildAvatar();
}
void LocalPlayer::updateInventory(bool forceUpdate)
void LocalPlayer::updateEquipped(bool forceUpdate)
{
MWWorld::Ptr player = GetPlayerPtr();
static bool invChanged = false;
static bool equipChanged = false;
if (forceUpdate)
invChanged = true;
equipChanged = true;
MWWorld::InventoryStore &invStore = player.getClass().getInventoryStore(player);
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; slot++)
@ -371,9 +371,10 @@ void LocalPlayer::updateInventory(bool forceUpdate)
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
if (it != invStore.end() && !::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), EquipedItem(slot)->refid))
{
invChanged = true;
equipChanged = true;
EquipedItem(slot)->refid = it->getCellRef().getRefId();
EquipedItem(slot)->health = it->getCellRef().getCharge();
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
{
MWMechanics::WeaponType weaptype;
@ -386,20 +387,101 @@ void LocalPlayer::updateInventory(bool forceUpdate)
}
else if (it == invStore.end() && !EquipedItem(slot)->refid.empty())
{
invChanged = true;
equipChanged = true;
EquipedItem(slot)->refid = "";
EquipedItem(slot)->count = 0;
EquipedItem(slot)->health = 0;
}
}
if (invChanged)
if (equipChanged)
{
RakNet::BitStream bs;
bs.ResetWritePointer();
GetNetworking()->GetPacket((RakNet::MessageID) ID_GAME_EQUIPMENT)->Packet(&bs, this, true);
GetNetworking()->SendData(&bs);
invChanged = false;
equipChanged = false;
}
}
void LocalPlayer::updateInventory(bool forceUpdate)
{
static bool invChanged = false;
if (forceUpdate)
invChanged = true;
MWWorld::Ptr player = GetPlayerPtr();
MWWorld::InventoryStore &invStore = player.getClass().getInventoryStore(player);
mwmp::Item item;
if(!invChanged)
for (vector<Item>::iterator iter = inventory.items.begin(); iter != inventory.items.end(); ++iter)
{
MWWorld::ContainerStoreIterator result(invStore.begin());
for (; result != invStore.end(); ++result)
{
item.refid = result->getCellRef().getRefId();
if(item.refid.find("$dynamic") != string::npos) // skip generated items (self enchanted for e.g.)
continue;
item.count = result->getRefData().getCount();
item.health = result->getCellRef().getCharge();
if(item == (*iter))
break;
}
if(result == invStore.end())
{
invChanged = true;
break;
}
}
if (!invChanged)
for (MWWorld::ContainerStoreIterator iter(invStore.begin()); iter != invStore.end(); ++iter)
{
item.refid = iter->getCellRef().getRefId();
if (item.refid.find("$dynamic") != string::npos) // skip generated items (self enchanted for e.g.)
continue;
item.count = iter->getRefData().getCount();
item.health = iter->getCellRef().getCharge();
vector<Item>::iterator result = inventory.items.begin();
for (; result != inventory.items.end(); result++)
{
if ((*result) == item)
break;
}
if (result == inventory.items.end())
{
invChanged = true;
break;
}
}
if (!invChanged)
return;
invChanged = false;
inventory.items.clear();
for (MWWorld::ContainerStoreIterator iter(invStore.begin()); iter != invStore.end(); ++iter)
{
item.refid = iter->getCellRef().getRefId();
if (item.refid.find("$dynamic") != string::npos) // skip generated items (self enchanted for e.g.)
continue;
item.count = iter->getRefData().getCount();
item.health = iter->getCellRef().getCharge();
inventory.items.push_back(item);
}
inventory.count = (unsigned int) inventory.items.size();
inventory.action = Inventory::UPDATE;
Main::get().getNetworking()->GetPacket(ID_GAME_INVENTORY)->Send(this);
}
void LocalPlayer::updateAttackState(bool forceUpdate)
@ -664,17 +746,23 @@ void LocalPlayer::setInventory()
MWWorld::Ptr ptrPlayer = GetPlayerPtr();
MWWorld::InventoryStore &ptrInventory = ptrPlayer.getClass().getInventoryStore(ptrPlayer);
ptrInventory.clear();
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; slot++)
{
mwmp::Item *currentItem = EquipedItem(slot);
//printf("Setting currentItem: %s in slot %i\n", currentItem->refid, slot);
if (!currentItem->refid.empty())
{
ptrInventory.equip(slot, ptrInventory.ContainerStore::add(EquipedItem(slot)->refid.c_str(), 1, ptrPlayer), ptrPlayer);
MWWorld::ContainerStoreIterator it = ptrInventory.begin();
for (; it != ptrInventory.end(); ++it) // find item in inventory
{
if (::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), currentItem->refid))
break;
}
if (it == ptrInventory.end()) // if not exists add item
ptrInventory.equip(slot, ptrInventory.ContainerStore::add(EquipedItem(slot)->refid.c_str(), 1, ptrPlayer), ptrPlayer);
else
ptrInventory.equip(slot, it, ptrPlayer);
}
}
}

@ -30,6 +30,7 @@ namespace mwmp
void updatePosition(bool forceUpdate = false);
void updateCell(bool forceUpdate = false);
void updateChar();
void updateEquipped(bool forceUpdate = false);
void updateInventory(bool forceUpdate = false);
void updateAttackState(bool forceUpdate = false);
void updateDeadState(bool forceUpdate = false);

@ -261,7 +261,7 @@ void Networking::ReceiveMessage(RakNet::Packet *packet)
{
if (packet->length == myPacket->headerSize())
{
getLocalPlayer()->updateInventory(true);
getLocalPlayer()->updateEquipped(true);
}
else
{
@ -613,6 +613,56 @@ void Networking::ReceiveMessage(RakNet::Packet *packet)
world->setMonth(getLocalPlayer()->month);
}
}
case ID_GAME_INVENTORY:
{
if (id == myid)
{
if (packet->length == myPacket->headerSize())
{
printf("ID_GAME_INVENTORY update only\n");
getLocalPlayer()->updateInventory(true);
GetPacket(ID_GAME_INVENTORY)->Send(getLocalPlayer());
}
else
{
myPacket->Packet(&bsIn, getLocalPlayer(), false);
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr();
MWWorld::ContainerStore &conStore = ptr.getClass().getContainerStore(ptr);
if (getLocalPlayer()->inventory.action == Inventory::ADDITEM)
{
for (unsigned int i = 0; i < getLocalPlayer()->inventory.count; i++)
{
mwmp::Item item = getLocalPlayer()->inventory.items[i];
MWWorld::Ptr itemPtr = *conStore.add(item.refid, item.count, ptr);
if(item.health != -1)
itemPtr.getCellRef().setCharge(item.health);
}
}
else if (getLocalPlayer()->inventory.action == Inventory::REMOVEITEM)
{
for (unsigned int i = 0; i < getLocalPlayer()->inventory.count; i++)
{
mwmp::Item item = getLocalPlayer()->inventory.items[i];
conStore.remove(item.refid, item.count, ptr);
}
}
else // update
{
conStore.clear();
for (unsigned int i = 0; i < getLocalPlayer()->inventory.count; i++)
{
mwmp::Item item = getLocalPlayer()->inventory.items[i];
MWWorld::Ptr itemPtr = *conStore.add(item.refid, item.count, ptr);
if(item.health != -1)
itemPtr.getCellRef().setCharge(item.health);
printf("%s %d %d\n", item.refid.c_str(), item.count, item.health);
}
getLocalPlayer()->setInventory(); // restore equipped items
}
}
}
break;
}
default:
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Custom message with identifier %i has arrived in initialization.", packet->data[0]);
}

@ -151,7 +151,7 @@ add_component_dir (openmw-mp
Packets/PlayerPacket Packets/PacketBaseInfo Packets/PacketPosition Packets/PacketEquipment Packets/PacketAttack
Packets/PacketDynamicStats Packets/PacketCell Packets/PacketDrawState Packets/PacketChatMessage
Packets/PacketCharGen Packets/PacketAttribute Packets/PacketSkill Packets/PacketLevel Packets/PacketHandshake
Packets/PacketGUIBoxes Packets/PacketClass Packets/PacketTime)
Packets/PacketGUIBoxes Packets/PacketClass Packets/PacketTime Packets/PacketInventory)
add_component_dir (fallback
fallback validate

@ -32,6 +32,24 @@ namespace mwmp
{
std::string refid;
int count;
int health;
inline bool operator==(const Item& rhs)
{
return refid == rhs.refid && count == rhs.count && health == rhs.health;
}
};
struct Inventory
{
std::vector<Item> items;
unsigned int count;
enum ACTION_TYPE
{
UPDATE = 0,
ADDITEM,
REMOVEITEM
};
int action; //0 - FullUpdate, 1 - AddItem, 2 - RemoveItem
};
class BasePlayer
@ -62,7 +80,8 @@ namespace mwmp
BasePlayer(RakNet::RakNetGUID guid) : guid(guid)
{
inventory.action = 0;
inventory.count = 0;
}
BasePlayer()
@ -147,6 +166,7 @@ namespace mwmp
int month;
int day;
double hour;
Inventory inventory;
protected:
ESM::Position pos;
@ -164,7 +184,6 @@ namespace mwmp
std::string chatMessage;
CGStage stage;
std::string passw;
};
}

@ -30,7 +30,8 @@ enum GameMessages
ID_HANDSHAKE,
ID_LOADED,
ID_GUI_MESSAGEBOX,
ID_GAME_TIME
ID_GAME_TIME,
ID_GAME_INVENTORY
};

@ -20,5 +20,6 @@ void PacketEquipment::Packet(RakNet::BitStream *bs, BasePlayer *player, bool sen
{
RW(player->EquipedItem(i)->refid, send);
RW(player->EquipedItem(i)->count, send);
RW(player->EquipedItem(i)->health, send);
}
}

@ -0,0 +1,44 @@
//
// Created by koncord on 22.10.16.
//
#include <components/openmw-mp/NetworkMessages.hpp>
#include "PacketInventory.hpp"
using namespace std;
using namespace mwmp;
PacketInventory::PacketInventory(RakNet::RakPeerInterface *peer) : BasePacket(peer)
{
packetID = ID_GAME_INVENTORY;
}
void PacketInventory::Packet(RakNet::BitStream *bs, BasePlayer *player, bool send)
{
BasePacket::Packet(bs, player, send);
RW(player->inventory.action, send);
if (!send)
player->inventory.items.clear();
else
player->inventory.count = (unsigned int) (player->inventory.items.size());
RW(player->inventory.count, send);
for (int i = 0; i < player->inventory.count; i++)
{
Item item;
if (send)
{
item = player->inventory.items[i];
RW(item.refid, send);
RW(item.count, send);
RW(item.health, send);
}
else
{
RW(item.refid, send);
RW(item.count, send);
RW(item.health, send);
player->inventory.items.push_back(item);
}
}
}

@ -0,0 +1,22 @@
//
// Created by koncord on 22.10.16.
//
#ifndef OPENMW_PACKETINVENTORY_HPP
#define OPENMW_PACKETINVENTORY_HPP
#include <components/openmw-mp/Packets/BasePacket.hpp>
namespace mwmp
{
class PacketInventory : public BasePacket
{
public:
PacketInventory(RakNet::RakPeerInterface *peer);
virtual void Packet(RakNet::BitStream *bs, BasePlayer *player, bool send);
};
}
#endif //OPENMW_PACKETINVENTORY_HPP

@ -27,6 +27,7 @@
#include "Packets/PacketGUIBoxes.hpp"
#include "Packets/PacketTime.hpp"
#include "Packets/PacketLoaded.hpp"
#include "Packets/PacketInventory.hpp"
#include "PacketsController.hpp"
@ -65,6 +66,7 @@ mwmp::PacketsController::PacketsController(RakNet::RakPeerInterface *peer)
AddPacket<PacketClass>(&packets, peer);
AddPacket<PacketTime>(&packets, peer);
AddPacket<PacketLoaded>(&packets, peer);
AddPacket<PacketInventory>(&packets, peer);
}

Loading…
Cancel
Save