mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-07-15 00:08:07 -04:00
Added serverGame library
This commit is contained in:
@@ -0,0 +1,676 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ResourceContainerObject.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "serverGame/FirstServerGame.h"
|
||||
#include "serverGame/ResourceContainerObject.h"
|
||||
|
||||
#include "UnicodeUtils.h"
|
||||
#include "serverGame/ContainerInterface.h"
|
||||
#include "serverGame/ResourceContainerController.h"
|
||||
#include "serverGame/ResourceTypeObject.h"
|
||||
#include "serverGame/ServerMessageForwarding.h"
|
||||
#include "serverGame/ServerResourceClassObject.h"
|
||||
#include "serverGame/ServerResourceContainerObjectTemplate.h"
|
||||
#include "serverGame/ServerUniverse.h"
|
||||
#include "serverGame/ServerWorld.h"
|
||||
#include "sharedFoundation/ConstCharCrcLowerString.h"
|
||||
#include "sharedFoundation/DynamicVariableList.h"
|
||||
#include "sharedGame/SharedObjectAttributes.h"
|
||||
#include "sharedGame/SharedResourceContainerObjectTemplate.h"
|
||||
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
|
||||
#include "sharedObject/ObjectTemplateList.h"
|
||||
#include "sharedObject/SlottedContainmentProperty.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
const SharedObjectTemplate * ResourceContainerObject::m_defaultSharedTemplate = NULL;
|
||||
|
||||
namespace ResourceContainerObjectNamespace
|
||||
{
|
||||
const std::string OBJVAR_RESOURCE_DATA("resourceData");
|
||||
};
|
||||
|
||||
using namespace ResourceContainerObjectNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
ResourceContainerObject::ResourceContainerObject(const ServerResourceContainerObjectTemplate* newTemplate) :
|
||||
TangibleObject (newTemplate),
|
||||
m_resourceType (NetworkId::cms_invalid),
|
||||
m_quantity (0),
|
||||
m_source (NetworkId::cms_invalid),
|
||||
m_maxQuantity (newTemplate->getMaxResources()),
|
||||
m_resourceName (),
|
||||
m_parentName ()
|
||||
{
|
||||
addMembersToPackages();
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ResourceContainerObject::~ResourceContainerObject()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns a shared template if none was given for this object.
|
||||
*
|
||||
* @return the shared template
|
||||
*/
|
||||
const SharedObjectTemplate * ResourceContainerObject::getDefaultSharedTemplate(void) const
|
||||
{
|
||||
static const ConstCharCrcLowerString templateName("object/resource_container/base/shared_resource_container_default.iff");
|
||||
|
||||
if (m_defaultSharedTemplate == NULL)
|
||||
{
|
||||
m_defaultSharedTemplate = safe_cast<const SharedObjectTemplate *>(ObjectTemplateList::fetch(templateName));
|
||||
WARNING_STRICT_FATAL(m_defaultSharedTemplate == NULL, ("Cannot create default shared object template %s", templateName.getString()));
|
||||
if (m_defaultSharedTemplate != NULL)
|
||||
ExitChain::add (removeDefaultTemplate, "ResourceContainerObject::removeDefaultTemplate");
|
||||
}
|
||||
return m_defaultSharedTemplate;
|
||||
} // ResourceContainerObject::getDefaultSharedTemplate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Cleans up the default shared template.
|
||||
*/
|
||||
void ResourceContainerObject::removeDefaultTemplate(void)
|
||||
{
|
||||
if (m_defaultSharedTemplate != NULL)
|
||||
{
|
||||
m_defaultSharedTemplate->releaseReference();
|
||||
m_defaultSharedTemplate = NULL;
|
||||
}
|
||||
} // ResourceContainerObject::removeDefaultTemplate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a default controller for this object.
|
||||
*
|
||||
* @return the object's controller
|
||||
*/
|
||||
Controller* ResourceContainerObject::createDefaultController(void)
|
||||
{
|
||||
Controller* _controller = new ResourceContainerController(this);
|
||||
NOT_NULL(_controller);
|
||||
|
||||
setController(_controller);
|
||||
return _controller;
|
||||
} // ResourceContainerObject::createDefaultController
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ResourceContainerObject::addResource(ResourceTypeObject const * const resourceType, int amount, NetworkId const & sourcePlayer)
|
||||
{
|
||||
if (!resourceType)
|
||||
return false;
|
||||
|
||||
return addResource(resourceType->getNetworkId(), amount, sourcePlayer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ResourceContainerObject::addResource(const NetworkId &resourceType, int amount, const NetworkId &sourcePlayer)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
WARNING_STRICT_FATAL(amount<0,("Use removeResource to remove resources from a ResourceContainer.\n"));
|
||||
return amount == 0;
|
||||
}
|
||||
|
||||
if (isAuthoritative())
|
||||
{
|
||||
if (m_quantity.get() + amount > m_maxQuantity.get())
|
||||
return false; // too much
|
||||
|
||||
if (m_quantity.get()==0)
|
||||
{
|
||||
// need to set the resource attribute objvar for imported resource type
|
||||
if (resourceType.getValue() > NetworkId::cms_maxNetworkIdWithoutClusterId)
|
||||
{
|
||||
DynamicVariableList const & objvars = getObjVars();
|
||||
if (!objvars.hasItem(OBJVAR_RESOURCE_DATA) || (DynamicVariable::STRING != objvars.getType(OBJVAR_RESOURCE_DATA)))
|
||||
{
|
||||
ResourceTypeObject const * const rto = ServerUniverse::getInstance().getImportedResourceTypeById(resourceType);
|
||||
if (!rto)
|
||||
return false;
|
||||
|
||||
std::string const resourceData = rto->getResourceTypeDataForExport();
|
||||
if (resourceData.empty())
|
||||
return false;
|
||||
|
||||
removeObjVarItem(OBJVAR_RESOURCE_DATA);
|
||||
IGNORE_RETURN(setObjVarItem(OBJVAR_RESOURCE_DATA, resourceData));
|
||||
}
|
||||
}
|
||||
|
||||
m_resourceType = resourceType; // note that m_quantity should be 0 only if this is a brand new crate
|
||||
m_source = sourcePlayer;
|
||||
|
||||
updateResourceNames();
|
||||
}
|
||||
else if (resourceType != m_resourceType.get())
|
||||
return false; // can't contain two different kinds of resource
|
||||
|
||||
m_quantity=m_quantity.get() + amount;
|
||||
if (sourcePlayer!=NetworkId::cms_invalid)
|
||||
addResourceSource(sourcePlayer, amount);
|
||||
|
||||
setAttributeRevisionDirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_STRICT_FATAL(true,("Cross-server container transfers are not supported.\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ResourceContainerObject::removeResource(const NetworkId &resourceType, int amount, std::vector<std::pair<NetworkId, int> > *sources)
|
||||
{
|
||||
while (amount > 0)
|
||||
{
|
||||
int actualAmountRemoved;
|
||||
NetworkId source(NetworkId::cms_invalid);
|
||||
if (!internalRemoveResource(resourceType, amount, source, actualAmountRemoved))
|
||||
return false;
|
||||
amount -= actualAmountRemoved;
|
||||
if (sources)
|
||||
{
|
||||
sources->push_back(std::pair<NetworkId, int>(source, actualAmountRemoved));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove up to a certain amount of resource. The resource removed will
|
||||
* always be from a single source player. It may be necessary to call this
|
||||
* function more than once to extract the total amount desired.
|
||||
*
|
||||
* @param resourceType The type of resource desired
|
||||
* @param amount The maximum amount to remove
|
||||
* @param source (output) Which player the resource came from (can be cms_invalid)
|
||||
* @param amountRemoved (output) The actual amount removed. Will be <= amount
|
||||
* @return True if at least 1 unit of the specified resource is removed
|
||||
*/
|
||||
bool ResourceContainerObject::internalRemoveResource(const NetworkId &resourceType, int amount, NetworkId &source, int &amountRemoved)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
WARNING_STRICT_FATAL(amount<0,("Trying to make a deposit with a withdrawal slip. (Called removeResource with a negative amount.)\n"));
|
||||
return amount == 0;
|
||||
}
|
||||
|
||||
if (isAuthoritative())
|
||||
{
|
||||
if (resourceType!=m_resourceType.get())
|
||||
return false; // wrong kind of resource
|
||||
amountRemoved = std::min(m_quantity.get(), amount);
|
||||
|
||||
// Identify source (if possible)
|
||||
if (m_source.get() == NetworkId::cms_invalid)
|
||||
{
|
||||
// multi-source container. Complicated
|
||||
source = NetworkId::cms_invalid;
|
||||
DynamicVariableList::NestedList varList(getObjVars(),"source");
|
||||
DynamicVariableList::NestedList::const_iterator var(varList.begin());
|
||||
if (var!=varList.end())
|
||||
{
|
||||
int varInt;
|
||||
if (var.getValue(varInt))
|
||||
{
|
||||
amountRemoved = std::min(amountRemoved, varInt);
|
||||
int remainingAmountFromSource = varInt - amountRemoved;
|
||||
source = NetworkId(var.getName());
|
||||
if (remainingAmountFromSource > 0)
|
||||
{
|
||||
IGNORE_RETURN(setObjVarItem(var.getNameWithPath(), remainingAmountFromSource));
|
||||
}
|
||||
else
|
||||
removeObjVarItem(var.getNameWithPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// single-source container. Simple
|
||||
source = m_source.get();
|
||||
}
|
||||
|
||||
// Adjust the quantity remaining
|
||||
m_quantity=m_quantity.get() - amountRemoved;
|
||||
if (m_quantity.get() == 0)
|
||||
IGNORE_RETURN(permanentlyDestroy(DeleteReasons::Consumed)); // containers delete themselves when empty
|
||||
|
||||
setAttributeRevisionDirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_STRICT_FATAL(true,("Cross-server container transfers are not supported.\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string ResourceContainerObject::getResourceCtsData() const
|
||||
{
|
||||
// resource came from another galaxy, so all the data is stored in the objvar
|
||||
DynamicVariableList const & objvars = getObjVars();
|
||||
if (objvars.hasItem(OBJVAR_RESOURCE_DATA) && (DynamicVariable::STRING == objvars.getType(OBJVAR_RESOURCE_DATA)))
|
||||
{
|
||||
std::string resourceData;
|
||||
IGNORE_RETURN(objvars.getItem(OBJVAR_RESOURCE_DATA, resourceData));
|
||||
return resourceData;
|
||||
}
|
||||
// resource came from this cluster, so construct the resource data
|
||||
else
|
||||
{
|
||||
ResourceTypeObject const * const typeObj = getResourceType();
|
||||
if (typeObj)
|
||||
return typeObj->getResourceTypeDataForExport();
|
||||
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void ResourceContainerObject::setResourceCtsData(int quantity, const std::string & resourceData)
|
||||
{
|
||||
if (!isAuthoritative())
|
||||
return;
|
||||
|
||||
if (m_resourceType.get().isValid())
|
||||
return;
|
||||
|
||||
if (m_quantity.get() > 0)
|
||||
return;
|
||||
|
||||
if (quantity <= 0)
|
||||
return;
|
||||
|
||||
if (resourceData.empty())
|
||||
return;
|
||||
|
||||
removeObjVarItem(OBJVAR_RESOURCE_DATA);
|
||||
NetworkId const importedResourceType = ResourceTypeObject::addImportedResourceType(resourceData);
|
||||
if (importedResourceType.isValid())
|
||||
{
|
||||
if (importedResourceType.getValue() > NetworkId::cms_maxNetworkIdWithoutClusterId)
|
||||
{
|
||||
// need to tell all proxy game servers, if any, to create the imported
|
||||
// resource type, if it hasn't already been created on that game server
|
||||
ProxyList const &proxyList = getExposedProxyList();
|
||||
if (!proxyList.empty())
|
||||
{
|
||||
ServerMessageForwarding::begin(std::vector<uint32>(proxyList.begin(), proxyList.end()));
|
||||
|
||||
GenericValueTypeMessage<std::pair<NetworkId, std::string> > const addImportedResourceTypeMsg("AddImportedResourceType", std::make_pair(importedResourceType, resourceData));
|
||||
ServerMessageForwarding::send(addImportedResourceTypeMsg);
|
||||
|
||||
ServerMessageForwarding::end();
|
||||
}
|
||||
}
|
||||
|
||||
IGNORE_RETURN(!addResource(importedResourceType, quantity, NetworkId::cms_invalid));
|
||||
}
|
||||
|
||||
if (!getObjVars().hasItem(OBJVAR_RESOURCE_DATA))
|
||||
{
|
||||
if (!m_resourceType.get().isValid() || (m_resourceType.get().getValue() > NetworkId::cms_maxNetworkIdWithoutClusterId))
|
||||
IGNORE_RETURN(setObjVarItem(OBJVAR_RESOURCE_DATA, resourceData));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string ResourceContainerObject::debugPrint() const
|
||||
{
|
||||
char buffer[20];
|
||||
IGNORE_RETURN(snprintf(buffer, 20, "%i",m_quantity.get()));
|
||||
ResourceTypeObject const * const r=ServerUniverse::getInstance().getResourceTypeById(m_resourceType.get());
|
||||
if (r)
|
||||
return (std::string("Resource Container with ")+buffer+" units of "+r->getResourceName());
|
||||
else
|
||||
return ("Invalid resource container");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Transfer resources from one container to another.
|
||||
* @return true if all the resource was tranferred, false if no resources
|
||||
* or less than the requested amount was transferred.
|
||||
* @todo Inter-server authority issues
|
||||
*/
|
||||
bool ResourceContainerObject::transferTo(ResourceContainerObject &destination, int amount)
|
||||
{
|
||||
if (isAuthoritative())
|
||||
{
|
||||
if ((m_resourceType.get() != destination.m_resourceType.get() && (destination.m_resourceType.get() != NetworkId::cms_invalid))
|
||||
|| amount > m_quantity.get())
|
||||
return false;
|
||||
|
||||
NetworkId sourcePlayer(NetworkId::cms_invalid);
|
||||
int amountRemoved = 0;
|
||||
while (amount > 0)
|
||||
{
|
||||
if (!internalRemoveResource(m_resourceType.get(), amount, sourcePlayer, amountRemoved))
|
||||
return false;
|
||||
if (!destination.addResource(m_resourceType.get(), amountRemoved, sourcePlayer))
|
||||
{
|
||||
// failed to add resource to destination, put it back into the source
|
||||
IGNORE_RETURN(addResource(m_resourceType.get(), amountRemoved, sourcePlayer));
|
||||
return false;
|
||||
}
|
||||
|
||||
amount -= amountRemoved;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_STRICT_FATAL(true,("Cross-server container transfers are not supported.\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Split this container into two containers
|
||||
* @param amount The amount to put in the new ResourceContainer
|
||||
* @param destContainer The container into which the new ResourceContainer should be placed, or cms_Invalid if no container
|
||||
* @param arrangementId -1 If destContainer is not slotted, otherwise the ID of the arrangement to use
|
||||
* @param newLocation The coordinates at which to place the new ResourceContainer. (Ignored if it is going into a non-positional container.)
|
||||
* @param actor The player making the split, or NULL
|
||||
*/
|
||||
|
||||
bool ResourceContainerObject::splitContainer(int amount, const CachedNetworkId &destContainer, int arrangementId, const Vector &newLocation, ServerObject *actor)
|
||||
{
|
||||
UNREF(actor);
|
||||
|
||||
bool result = false;
|
||||
|
||||
ResourceContainerObject *newCrate = NULL;
|
||||
|
||||
if (destContainer == CachedNetworkId::cms_cachedInvalid)
|
||||
{
|
||||
// create in world
|
||||
Transform tr;
|
||||
tr.setPosition_p(newLocation);
|
||||
newCrate = dynamic_cast<ResourceContainerObject*>(ServerWorld::createNewObject(getObjectTemplateName(), tr, 0, isPersisted()));
|
||||
}
|
||||
else if (arrangementId < 0)
|
||||
{
|
||||
// create in volume container
|
||||
ServerObject * destObject = safe_cast<ServerObject *>(destContainer.getObject());
|
||||
if (destObject == NULL)
|
||||
return false;
|
||||
newCrate = dynamic_cast<ResourceContainerObject*>(ServerWorld::createNewObject(getObjectTemplateName(), *destObject, isPersisted()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// create in slotted container
|
||||
ServerObject * destObject = safe_cast<ServerObject *>(destContainer.getObject());
|
||||
if (destObject == NULL)
|
||||
return false;
|
||||
const SlottedContainmentProperty* containmentProperty = ContainerInterface::getSlottedContainmentProperty(*destObject);
|
||||
if (containmentProperty == NULL)
|
||||
return false;
|
||||
const SlottedContainmentProperty::SlotArrangement & slots = containmentProperty->getSlotArrangement(arrangementId);
|
||||
if (slots.empty())
|
||||
return false;
|
||||
newCrate = dynamic_cast<ResourceContainerObject*>(ServerWorld::createNewObject(getObjectTemplateName(), *destObject, slots.front(), isPersisted()));
|
||||
}
|
||||
if (newCrate)
|
||||
{
|
||||
result = transferTo(*newCrate, amount);
|
||||
|
||||
if (!result)
|
||||
IGNORE_RETURN(newCrate->permanentlyDestroy(DeleteReasons::BadContainerTransfer));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void ResourceContainerObject::updateResourceNames()
|
||||
{
|
||||
if (!isAuthoritative())
|
||||
return;
|
||||
|
||||
m_resourceName.set (Unicode::emptyString);
|
||||
m_parentName.set (std::string ());
|
||||
m_resourceNameId.set (StringId::cms_invalid);
|
||||
|
||||
setAttributeRevisionDirty();
|
||||
|
||||
if (!m_resourceType.get ().isValid ())
|
||||
{
|
||||
setObjectName (Unicode::emptyString);
|
||||
return;
|
||||
}
|
||||
|
||||
//-- setup the parent inheritance chain.
|
||||
//-- the client needs this information
|
||||
|
||||
ResourceTypeObject const * const type = ServerUniverse::getInstance().getResourceTypeById(m_resourceType.get());
|
||||
|
||||
if (type)
|
||||
{
|
||||
m_resourceName = Unicode::narrowToWide(type->getResourceName ());
|
||||
if ((m_resourceName.get())[0] == '@')
|
||||
{
|
||||
m_resourceNameId = StringId(Unicode::wideToNarrow(m_resourceName.get()));
|
||||
}
|
||||
|
||||
ResourceClassObject const & parentClass = type->getParentClass();
|
||||
|
||||
m_parentName = parentClass.getResourceClassName ();
|
||||
|
||||
ResourceClassObject const * const parentClass2 = parentClass.getParent ();
|
||||
|
||||
if (parentClass2)
|
||||
{
|
||||
setObjectName(Unicode::emptyString);
|
||||
setObjectNameStringId (parentClass2->getFriendlyName());
|
||||
}
|
||||
else
|
||||
{
|
||||
setObjectName(Unicode::emptyString);
|
||||
setObjectNameStringId (parentClass.getFriendlyName());
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
DEBUG_WARNING (true, ("Unable to find specified resource type %s", m_resourceType.get ().getValueString ().c_str ()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
std::string ResourceContainerObject::getItemLog() const
|
||||
{
|
||||
char tmpBuffer[1024];
|
||||
IGNORE_RETURN(snprintf(tmpBuffer, sizeof(tmpBuffer) - 1, ": %d units of %s", getQuantity(), Unicode::wideToNarrow(m_resourceName.get()).c_str()));
|
||||
tmpBuffer[sizeof(tmpBuffer)-1] = 0;
|
||||
|
||||
return TangibleObject::getItemLog() + tmpBuffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void ResourceContainerObject::getAttributes(stdvector<std::pair<std::string, Unicode::String> >::fwd &data) const
|
||||
{
|
||||
TangibleObject::getAttributes(data);
|
||||
|
||||
char valueBuffer[32];
|
||||
IGNORE_RETURN(snprintf (valueBuffer, sizeof (valueBuffer), "%d/%d", getQuantity (), getMaxQuantity ()));
|
||||
data.push_back (std::make_pair (SharedObjectAttributes::resource_contents, Unicode::narrowToWide (valueBuffer)));
|
||||
|
||||
ResourceTypeObject const * const typeObj = getResourceType();
|
||||
if (typeObj)
|
||||
{
|
||||
data.push_back (std::make_pair (SharedObjectAttributes::resource_name, Unicode::narrowToWide(typeObj->getResourceName ())));
|
||||
|
||||
ResourceClassObject const & parent = typeObj->getParentClass ();
|
||||
data.push_back (std::make_pair (SharedObjectAttributes::resource_class, Unicode::narrowToWide ("@" + parent.getFriendlyName ().getCanonicalRepresentation())));
|
||||
|
||||
typeObj->getResourceAttributes(data);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void ResourceContainerObject::endBaselines()
|
||||
{
|
||||
TangibleObject::endBaselines();
|
||||
|
||||
if (isAuthoritative())
|
||||
{
|
||||
// if resource is an imported resource, register the imported resource type on
|
||||
// this game server, if it hasn't already been registered on this game server;
|
||||
// this must be done on each game server as it receives the resource container
|
||||
DynamicVariableList const & objvars = getObjVars();
|
||||
if (objvars.hasItem(OBJVAR_RESOURCE_DATA) && (DynamicVariable::STRING == objvars.getType(OBJVAR_RESOURCE_DATA)))
|
||||
{
|
||||
bool const alreadyRegistered = (m_resourceType.get().isValid() && (m_resourceType.get().getValue() > NetworkId::cms_maxNetworkIdWithoutClusterId) && ServerUniverse::getInstance().getImportedResourceTypeById(m_resourceType.get()));
|
||||
if (!alreadyRegistered)
|
||||
{
|
||||
std::string resourceData;
|
||||
IGNORE_RETURN(objvars.getItem(OBJVAR_RESOURCE_DATA, resourceData));
|
||||
NetworkId const importedResourceType = ResourceTypeObject::addImportedResourceType(resourceData);
|
||||
if (importedResourceType.isValid())
|
||||
{
|
||||
if (importedResourceType != m_resourceType.get())
|
||||
m_resourceType = importedResourceType;
|
||||
|
||||
if (importedResourceType.getValue() <= NetworkId::cms_maxNetworkIdWithoutClusterId)
|
||||
removeObjVarItem(OBJVAR_RESOURCE_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateResourceNames();
|
||||
}
|
||||
else
|
||||
{
|
||||
// if resource is an imported resource, register the imported resource type on
|
||||
// this game server, if it hasn't already been registered on this game server;
|
||||
// this must be done on each game server as it receives the resource container
|
||||
if (m_resourceType.get().isValid() && (m_resourceType.get().getValue() > NetworkId::cms_maxNetworkIdWithoutClusterId) && !ServerUniverse::getInstance().getImportedResourceTypeById(m_resourceType.get()))
|
||||
{
|
||||
DynamicVariableList const & objvars = getObjVars();
|
||||
if (objvars.hasItem(OBJVAR_RESOURCE_DATA) && (DynamicVariable::STRING == objvars.getType(OBJVAR_RESOURCE_DATA)))
|
||||
{
|
||||
std::string resourceData;
|
||||
IGNORE_RETURN(objvars.getItem(OBJVAR_RESOURCE_DATA, resourceData));
|
||||
IGNORE_RETURN(ResourceTypeObject::addImportedResourceType(resourceData));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void ResourceContainerObject::addResourceSource(const NetworkId &source, int amount)
|
||||
{
|
||||
if (source == m_source.get())
|
||||
return; // single-source container adding more resource from the same source -- no change needed
|
||||
|
||||
if (m_source.get() != NetworkId::cms_invalid)
|
||||
{
|
||||
// converting a single-source container into a multi-source container. All resources except the ones from the new source get credited to the first source
|
||||
const std::string & varname = std::string("source.") + m_source.get().getValueString();
|
||||
IGNORE_RETURN(setObjVarItem(varname, m_quantity.get() - amount));
|
||||
m_source = NetworkId::cms_invalid;
|
||||
}
|
||||
|
||||
const std::string & varname = std::string("source.") + source.getValueString ();
|
||||
int intvar = 0;
|
||||
if (getObjVars().getItem(varname,intvar))
|
||||
{
|
||||
IGNORE_RETURN(setObjVarItem(varname, intvar+amount));
|
||||
}
|
||||
else
|
||||
{
|
||||
removeObjVarItem(varname);
|
||||
|
||||
IGNORE_RETURN(setObjVarItem(varname, amount));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ResourceContainerObject::removeResourceWithoutExperience(const NetworkId &resourceType, int amount)
|
||||
{
|
||||
while (amount > 0)
|
||||
{
|
||||
int amountRemoved = 0;
|
||||
NetworkId source;
|
||||
if (!internalRemoveResource(resourceType, amount, source, amountRemoved))
|
||||
return false;
|
||||
amount -= amountRemoved;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
ResourceTypeObject const * const ResourceContainerObject::getResourceType() const
|
||||
{
|
||||
return ServerUniverse::getInstance().getResourceTypeById(m_resourceType.get());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
NetworkId ResourceContainerObject::getResourceTypeId() const
|
||||
{
|
||||
return m_resourceType.get();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* For debugging only, convert this container to the recycled equivalent.
|
||||
* This is not intended for uses other than debugging, because the container
|
||||
* might not be the right kind of container to hold the recycled resource
|
||||
*/
|
||||
bool ResourceContainerObject::debugRecycle()
|
||||
{
|
||||
if (!isAuthoritative())
|
||||
return false;
|
||||
|
||||
ResourceTypeObject const * const resourceType=getResourceType();
|
||||
if (!resourceType)
|
||||
return false;
|
||||
if (resourceType->isRecycled())
|
||||
return true; // already recycled
|
||||
ResourceTypeObject const * const recycledType=resourceType->getRecycledVersion();
|
||||
if (!recycledType)
|
||||
return false; // no recycled version of this resource
|
||||
DEBUG_FATAL(recycledType == resourceType,("Programmer bug: resourceType->getRecycledVersion on %s returned the same type.",resourceType->getResourceName().c_str()));
|
||||
|
||||
m_resourceType = recycledType->getNetworkId();
|
||||
updateResourceNames();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
Reference in New Issue
Block a user