2010-05-06 00:08:41 +00:00
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
# ifndef RY_INVENTORIES_H
# define RY_INVENTORIES_H
# include "nel/misc/types_nl.h"
# include <stdio.h>
# include "nel/misc/bit_mem_stream.h"
# include "nel/misc/time_nl.h"
# include "nel/misc/enum_bitset.h"
# include "nel/net/service.h"
/* ******
define for pet animal
WARNING ! ! ! ! ! If you change MAX_INVENTORY_ANIMAL value , you ' ll have to :
- change code around all nlctassert that should raise because of change
- search in file MAX_INVENTORY_ANIMAL in all XML ( including database . xml AND local_database . xml ) to do correct changes
* * * * * * */
# define MAX_PACK_ANIMAL 3
# define MAX_MEKTOUB_MOUNT 1
# define MAX_OTHER_PET 0
# define MAX_INVENTORY_ANIMAL ( MAX_PACK_ANIMAL + MAX_MEKTOUB_MOUNT )
// This give by which value the WEIGHT in database must be divided to get the value in Kg
// valueKg= valueDb / DB_WEIGHT_SCALE
# define DB_WEIGHT_SCALE 100
namespace INVENTORIES
{
/** Domain wide unique id for item (on 64 bits)
* Use a combination of unix time , shardId and current second serial number .
*/
struct TItemId
{
/// create a new item id
TItemId ( )
{
uint32 now = NLMISC : : CTime : : getSecondsSince1970 ( ) ;
if ( now ! = _LastCreation )
{
_LastCreation = now ;
_SerialNumber = 0 ;
}
_CreateTime = now ;
_SerialNumber = _NextSerialNumber + + ;
_ShardId = NLNET : : IService : : getInstance ( ) - > getShardId ( ) ;
}
/// Build from a raw id value
TItemId ( uint64 rawId )
{
_RawId = rawId ;
}
/// build an item id from a string
TItemId ( const std : : string & idStr )
{
_RawId = 0 ;
uint32 shardId = 0 ;
uint32 serialNum = 0 ;
if ( sscanf ( idStr . c_str ( ) , " [%u:%x:%u] " , & shardId , & _CreateTime , & serialNum ) = = 3 )
{
_ShardId = shardId ;
_SerialNumber = serialNum ;
}
}
/// Get the raw id value
uint64 getRawId ( ) const
{
return _RawId ;
}
/// hum... serial
void serial ( NLMISC : : IStream & s )
{
s . serial ( _RawId ) ;
}
/// convert to a standard string representation (that can be parsed back as itemId)
std : : string toString ( ) const
{
return NLMISC : : toString ( " [%u:0x%x:%u] " , _ShardId , _CreateTime , _SerialNumber ) ;
}
bool operator = = ( const TItemId & other ) const
{
return _RawId = = other . _RawId ;
}
bool operator < ( const TItemId & other ) const
{
return _RawId < other . _RawId ;
}
private :
union
{
// the 64 bits row ID
uint64 _RawId ;
struct
{
// creation date in unix time
uint32 _CreateTime ;
// the serial number (during the creation second)
uint32 _SerialNumber : 24 ;
// the shard id
uint32 _ShardId : 8 ;
} ;
} ;
/// Static counter to remember the date of the current serial
static uint32 _LastCreation ;
/// The serial number in the current second
static uint32 _NextSerialNumber ;
} ;
enum THandSlot
{
right = 0 ,
left ,
NB_HAND_SLOT
} ;
enum TInventory
{
// TODO : remove handling, merge it with equipement
handling = 0 ,
temporary , // 1
equipment , // 2
bag , // 3
pet_animal , // 4 Character can have 5 pack animal
pet_animal1 = pet_animal , // for toString => TInventory convertion
pet_animal2 ,
pet_animal3 ,
pet_animal4 ,
max_pet_animal , // 8
NUM_INVENTORY = max_pet_animal , // 8
UNDEFINED = NUM_INVENTORY , // 8
exchange , // 9 This is not a bug : exchange is a fake inventory
exchange_proposition , // 10 and should not count in the number of inventory
// same for botChat trading.
trading , // 11
reward_sharing , // 12 fake inventory, not in database.xml. Used by the item info protocol only
guild , // 13 (warning: number stored in guild saved file)
player_room , // 14
NUM_ALL_INVENTORY // warning: distinct from NUM_INVENTORY
} ;
/**
* Convert an inventory name to a TInventory enum
* \ param str the input string
* \ return the TInventory associated to this string ( UNDEFINED if the string cannot be interpreted )
*/
TInventory toInventory ( const std : : string & str ) ;
/**
* Return inventory name
* \ param inv TInventory identify
* \ return name of inventory ( or unknown if nit exist )
*/
const std : : string & toString ( TInventory inv ) ;
/**
* get the name of an inventory in the data base . Use this API to fill the user database
* \ return if the specified inventory is supported
* \ param inventory : the inventory enum
* \ param retValue ; the returned string
*/
//bool getDatabaseString( std::string & retValue,TInventory inventory );
extern const char * DatabaseStringFromEInventory [ NUM_ALL_INVENTORY ] ;
const uint MaxNbPackers = MAX_INVENTORY_ANIMAL ;
class CInventoryCategoryForCharacter
{
public :
enum TInventoryId
{
Bag ,
Packers ,
Room = Packers + MaxNbPackers ,
InvalidInvId ,
NbInventoryIds = InvalidInvId
} ;
static const char * InventoryStr [ NbInventoryIds ] ;
static const uint InventoryNbSlots [ NbInventoryIds ] ;
enum TSlotBitSize
{
SlotBitSize = 10
} ;
static std : : string getDbStr ( TInventoryId invId ) ;
static bool needPlainInfoVersionTransfer ( ) { return false ; } // incrementation is sufficient
} ;
class CInventoryCategoryForGuild
{
public :
enum TInventoryId
{
GuildInvId ,
InvalidInvId ,
NbInventoryIds = InvalidInvId
} ;
static const char * InventoryStr [ NbInventoryIds ] ;
static const uint InventoryNbSlots [ NbInventoryIds ] ;
enum TSlotBitSize
{
SlotBitSize = 10
} ;
static std : : string getDbStr ( TInventoryId invId ) ;
static bool needPlainInfoVersionTransfer ( ) { return true ; } // incrementation is not sufficient because can incremented when player offline, and some values are skipped
} ;
//const uint NbBitsForInventoryId = 3; // must include InvalidInvId
/* ******
WARNING ! ! ! ! ! If you change those value , you ' ll have to :
- change database . xml AND local_database . xml
- change slotids server < - > client sizes
* * * * * * * */
const uint NbBagSlots = 500 ;
const uint NbPackerSlots = 500 ;
const uint NbRoomSlots = 1000 ;
const uint NbGuildSlots = 1000 ;
const uint NbTempInvSlots = 16 ;
enum TItemPropId
{
Sheet ,
Quality ,
Quantity ,
UserColor ,
Locked ,
Weight ,
NameId ,
Enchant ,
ItemClass ,
ItemBestStat ,
Price ,
ResaleFlag ,
PrerequisitValid ,
Worned ,
NbItemPropId
} ;
const uint NbBitsForItemPropId = 4 ; // TODO: replace this constant by an inline function using NbItemPropId
const uint LowNumberBound = 7 ;
const uint LowNumberBits = 3 ;
const uint InfoVersionBitSize = 8 ;
extern const char * InfoVersionStr ;
/// toString(), alternate version for TInventoryId
inline const std : : string toString ( CInventoryCategoryForCharacter : : TInventoryId invId )
{
return std : : string ( CInventoryCategoryForCharacter : : InventoryStr [ invId ] ) ;
}
/// toString(), alternate version for TInventoryId
inline const std : : string toString ( CInventoryCategoryForGuild : : TInventoryId invId )
{
return std : : string ( CInventoryCategoryForGuild : : InventoryStr [ invId ] ) ;
}
/// Return the inventory db root string
inline std : : string CInventoryCategoryForCharacter : : getDbStr ( TInventoryId invId )
{
return std : : string ( " INVENTORY: " ) + INVENTORIES : : toString ( invId ) ;
}
/// Return the inventory db root string
inline std : : string CInventoryCategoryForGuild : : getDbStr ( TInventoryId invId )
{
return INVENTORIES : : toString ( invId ) + " :INVENTORY " ;
}
/**
* Slot in inventory ( bag , room , etc . )
*
* TODO : Check version at client startup
*/
class CItemSlot
{
public :
static const uint DataBitSize [ NbItemPropId ] ;
static const char * ItemPropStr [ NbItemPropId ] ;
/// Return the version
static uint16 getVersion ( ) { return 0 ; }
/// Default constructor
CItemSlot ( ) { }
/// Constructor. Warning: does not reset the values!
explicit CItemSlot ( uint32 slotIndex ) : _SlotIndex ( slotIndex ) { }
/// Change the slot index
void setSlotIndex ( uint32 slotIndex ) { _SlotIndex = slotIndex ; }
/// Return the slot index
uint32 getSlotIndex ( ) const { return _SlotIndex ; }
/// Set all properties to 0
void reset ( )
{
for ( uint i = 0 ; i ! = NbItemPropId ; + + i )
_ItemProp [ i ] = 0 ;
}
/// Set a property
void setItemProp ( TItemPropId id , sint32 value )
{
_ItemProp [ id ] = value ;
}
/// Get a property
sint32 getItemProp ( TItemPropId id ) const
{
return _ItemProp [ id ] ;
}
/// Serial from/to bit stream
template < class CInventoryCategoryTemplate >
2012-04-07 18:04:08 +00:00
void serialAll ( NLMISC : : CBitMemStream & bms , const CInventoryCategoryTemplate * /* templ */ = 0 )
2010-05-06 00:08:41 +00:00
{
bms . serial ( _SlotIndex , CInventoryCategoryTemplate : : SlotBitSize ) ;
uint i ;
// SHEET, QUALITY, QUANTITY and USER_COLOR never require compression
for ( i = 0 ; i < 4 ; + + i )
bms . serial ( ( uint32 & ) _ItemProp [ i ] , DataBitSize [ i ] ) ;
// For all other the compression is simple the first bit indicates if the value is zero
if ( bms . isReading ( ) )
{
for ( ; i < NbItemPropId ; + + i )
{
bool b ;
bms . serialBit ( b ) ;
if ( b )
_ItemProp [ i ] = 0 ;
else
bms . serial ( ( uint32 & ) _ItemProp [ i ] , DataBitSize [ i ] ) ;
}
}
else
{
for ( ; i ! = NbItemPropId ; + + i )
{
bool b = ( _ItemProp [ i ] = = 0 ) ;
bms . serialBit ( b ) ;
if ( ! b )
bms . serial ( ( uint32 & ) _ItemProp [ i ] , DataBitSize [ i ] ) ;
}
}
}
/// Serial from/to bit stream
template < class CInventoryCategoryTemplate >
2012-04-07 18:04:08 +00:00
void serialOneProp ( NLMISC : : CBitMemStream & bms , const CInventoryCategoryTemplate * /* templ */ = 0 )
2010-05-06 00:08:41 +00:00
{
bms . serial ( _SlotIndex , CInventoryCategoryTemplate : : SlotBitSize ) ;
bms . serial ( _OneProp ) ;
}
/// Set all properties from another object
void copyFrom ( const CItemSlot & src )
{
for ( uint i = 0 ; i ! = NbItemPropId ; + + i )
{
_ItemProp [ i ] = src . _ItemProp [ i ] ;
}
}
// Assignment operator
CItemSlot & operator = ( const CItemSlot & src )
{
copyFrom ( src ) ;
_SlotIndex = src . _SlotIndex ;
return * this ;
}
private :
struct COneProp
{
TItemPropId ItemPropId ;
sint32 ItemPropValue ;
void serial ( NLMISC : : CBitMemStream & bms )
{
bms . serial ( ( uint32 & ) ItemPropId , NbBitsForItemPropId ) ;
bms . serial ( ( uint32 & ) ItemPropValue , CItemSlot : : DataBitSize [ ItemPropId ] ) ;
}
} ;
union
{
/// All item properties
sint32 _ItemProp [ NbItemPropId ] ;
/// Only one prop (needs to be here because a CItemSlot can't be stored in an union because of the constructors)
COneProp _OneProp ;
} ;
/// Slot number
uint32 _SlotIndex ;
public :
// Accessors (for internal use only)
COneProp & getOneProp ( ) { return _OneProp ; }
} ;
// Define constants for inventory modification flag (TODO: add ic_slot_count)
enum TInventoryChange
{
ic_total_bulk = 1 < < 0 ,
ic_total_weight = 1 < < 1 ,
ic_item_list = 1 < < 2 ,
ic_other = 1 < < 3 ,
} ;
typedef NLMISC : : CEnumBitset < TInventoryChange > TInventoryChangeFlags ;
// Define constants for item modification callback flag
enum TItemChange
{
itc_bulk = 1 < < 0 ,
itc_weight = 1 < < 1 ,
itc_enchant = 1 < < 2 ,
itc_hp = 1 < < 3 ,
itc_inserted = 1 < < 4 ,
itc_removed = 1 < < 5 ,
itc_lock_state = 1 < < 6 ,
itc_info_version = 1 < < 7 ,
itc_worned = 1 < < 8 ,
} ;
typedef NLMISC : : CEnumBitset < TItemChange > TItemChangeFlags ;
enum // for pseudo constants
{
INSERT_IN_FIRST_FREE_SLOT = 0xFFFFFFFF ,
REMOVE_MAX_STACK_QUANTITY = 0xFFFFFFFF ,
INVALID_INVENTORY_SLOT = INSERT_IN_FIRST_FREE_SLOT ,
} ;
} // namespace INVENTORIES
# endif // RY_INVENTORIES_H
/* End of inventories.h */