mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-07-15 00:08:07 -04:00
566 lines
18 KiB
C++
Executable File
566 lines
18 KiB
C++
Executable File
//========================================================================
|
|
//
|
|
// DraftSchematicObject.cpp
|
|
//
|
|
// copyright 2001 Sony Online Entertainment
|
|
//
|
|
//========================================================================
|
|
|
|
#include "serverGame/FirstServerGame.h"
|
|
#include "serverGame/DraftSchematicObject.h"
|
|
|
|
#include "UnicodeUtils.h"
|
|
#include "serverGame/ManufactureSchematicObject.h"
|
|
#include "serverGame/ObjectIdManager.h"
|
|
#include "serverGame/ServerController.h"
|
|
#include "serverGame/ServerManufactureSchematicObjectTemplate.h"
|
|
#include "serverScript/GameScriptObject.h"
|
|
#include "serverScript/ScriptParameters.h"
|
|
#include "sharedFile/TreeFile.h"
|
|
#include "sharedFoundation/ConstCharCrcLowerString.h"
|
|
#include "sharedFoundation/ConstCharCrcString.h"
|
|
#include "sharedFoundation/Crc.h"
|
|
#include "sharedGame/SharedObjectTemplate.h"
|
|
#include "sharedNetworkMessages/MessageQueueResourceWeights.h"
|
|
#include "sharedObject/NetworkController.h"
|
|
#include "sharedObject/ObjectTemplateList.h"
|
|
|
|
// ======================================================================
|
|
// local constants
|
|
|
|
|
|
static const int MAX_ATTRIBUTES = 32;
|
|
static const std::string REQUEST_RESOURCE_WEIGHTS_SCRIPT_METHOD("OnRequestResourceWeights");
|
|
|
|
|
|
// ======================================================================
|
|
// static members
|
|
|
|
DraftSchematicObject::SchematicMap * DraftSchematicObject::m_schematics = NULL;
|
|
const SharedObjectTemplate * DraftSchematicObject::m_defaultSharedTemplate = NULL;
|
|
|
|
|
|
// ======================================================================
|
|
|
|
/**
|
|
* Class constructor.
|
|
*
|
|
* @param newTemplate template to create the schematic from.
|
|
*/
|
|
DraftSchematicObject::DraftSchematicObject(
|
|
const ServerDraftSchematicObjectTemplate* newTemplate) :
|
|
IntangibleObject(newTemplate),
|
|
m_slots(),
|
|
m_attributes(),
|
|
m_experimentalAttributes(),
|
|
m_combinedCrc(newTemplate->getCrcName().getCrc(), getSharedTemplate()->getCrcName().getCrc())
|
|
{
|
|
int i;
|
|
ServerDraftSchematicObjectTemplate::IngredientSlot slot;
|
|
|
|
// put the slots in the name lookup map
|
|
int count = newTemplate->getSlotsCount();
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
newTemplate->getSlots(slot, i);
|
|
m_slots.insert(std::make_pair(slot.name, i));
|
|
}
|
|
|
|
// get the experimental attributes from the attributes, and create a map
|
|
// between them
|
|
int minValue = 0, maxValue = 0;
|
|
count = getAttribsCount();
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
const SharedDraftSchematicObjectTemplate::SchematicAttribute & attrib =
|
|
getAttrib(i);
|
|
|
|
m_attributes[attrib.name] = i;
|
|
if (!attrib.experiment.getTable().empty() && !attrib.experiment.getText().empty())
|
|
{
|
|
getAttribMinMax(i, minValue, maxValue);
|
|
if (minValue != maxValue)
|
|
m_experimentalAttributes[attrib.experiment].push_back(attrib.name);
|
|
}
|
|
}
|
|
} // DraftSchematicObject::DraftSchematicObject
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Class destructor.
|
|
*/
|
|
DraftSchematicObject::~DraftSchematicObject()
|
|
{
|
|
} // DraftSchematicObject::~DraftSchematicObject
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Returns a shared template if none was given for this object.
|
|
*
|
|
* @return the shared template
|
|
*/
|
|
const SharedObjectTemplate * DraftSchematicObject::getDefaultSharedTemplate(void) const
|
|
{
|
|
static const ConstCharCrcLowerString templateName("object/draft_schematic/base/shared_draft_schematic_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, "DraftSchematicObject::removeDefaultTemplate");
|
|
}
|
|
return m_defaultSharedTemplate;
|
|
} // DraftSchematicObject::getDefaultSharedTemplate
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Cleans up the default shared template.
|
|
*/
|
|
void DraftSchematicObject::removeDefaultTemplate(void)
|
|
{
|
|
if (m_defaultSharedTemplate != NULL)
|
|
{
|
|
m_defaultSharedTemplate->releaseReference();
|
|
m_defaultSharedTemplate = NULL;
|
|
}
|
|
} // DraftSchematicObject::removeDefaultTemplate
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Requests info about resource weights for a given draft schematic.
|
|
*
|
|
* @param requester the player making the request
|
|
* @param draftSchematicName the schematic the player wants to know about
|
|
*/
|
|
void DraftSchematicObject::requestResourceWeights(ServerObject & requester, uint32 draftSchematicCrc)
|
|
{
|
|
if (requester.getClient() == NULL)
|
|
{
|
|
WARNING (true, ("DraftSchematicObject::requestResourceWeights invalid client for [%s]", requester.getNetworkId ().getValueString ().c_str ()));
|
|
return;
|
|
}
|
|
|
|
const DraftSchematicObject * const schematic = getSchematic(draftSchematicCrc);
|
|
if (schematic == NULL)
|
|
{
|
|
WARNING (true, ("DraftSchematicObject::requestResourceWeights invalid schematic [%lu] for [%s]", draftSchematicCrc, requester.getNetworkId ().getValueString ().c_str ()));
|
|
return;
|
|
}
|
|
|
|
const ServerDraftSchematicObjectTemplate * const schematicTemplate = safe_cast<const ServerDraftSchematicObjectTemplate *>(schematic->getObjectTemplate());
|
|
if (schematicTemplate == NULL)
|
|
{
|
|
WARNING (true, ("DraftSchematicObject::requestResourceWeights invalid schematic template [%lu] for [%s]", draftSchematicCrc, requester.getNetworkId ().getValueString ().c_str ()));
|
|
return;
|
|
}
|
|
|
|
std::vector<const char *> desiredAttribs;
|
|
{
|
|
for (NameToIndexMap::const_iterator i = schematic->m_attributes.begin(); i != schematic->m_attributes.end(); ++i)
|
|
desiredAttribs.push_back((*i).first.getText().c_str());
|
|
}
|
|
|
|
std::vector<const char *> attributes(MAX_ATTRIBUTES * 2, static_cast<const char *>(NULL));
|
|
std::vector<int> slots(MAX_ATTRIBUTES * 2, 0);
|
|
std::vector<int> counts(MAX_ATTRIBUTES * 2, 0);
|
|
std::vector<int> weights(MAX_ATTRIBUTES * 2 * Crafting::RA_numResourceAttributes * 2, 0);
|
|
ScriptParams params;
|
|
params.addParam(requester.getNetworkId());
|
|
params.addParam(desiredAttribs);
|
|
params.addParam(attributes);
|
|
params.addParam(slots);
|
|
params.addParam(counts);
|
|
params.addParam(weights);
|
|
|
|
// call script function
|
|
GameScriptObject::runOneScript(schematicTemplate->getManufactureScripts(0), REQUEST_RESOURCE_WEIGHTS_SCRIPT_METHOD, "Os[s*[i*[i*[i*[", params);
|
|
|
|
const std::vector<const char *> & newAttributes = params.getStringArrayParam(2);
|
|
const std::vector<int> & newSlots = params.getIntArrayParam(3);
|
|
const std::vector<int> & newCounts = params.getIntArrayParam(4);
|
|
const std::vector<int> & newWeights = params.getIntArrayParam(5);
|
|
std::vector<int>::const_iterator slotIter(newSlots.begin());
|
|
std::vector<int>::const_iterator countIter(newCounts.begin());
|
|
std::vector<int>::const_iterator weightIter(newWeights.begin());
|
|
|
|
MessageQueueResourceWeights * const message = new MessageQueueResourceWeights(schematic->getCombinedCrc());
|
|
|
|
// find out how many attributes were returned
|
|
int attribCount = 0;
|
|
{
|
|
for (std::vector<const char *>::const_iterator i(newAttributes.begin());
|
|
i != newAttributes.end(); ++i, ++attribCount)
|
|
{
|
|
if (*i == NULL)
|
|
break;
|
|
}
|
|
}
|
|
attribCount /= 2;
|
|
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
for (int j = 0; j < attribCount; ++j)
|
|
{
|
|
const StringId sid("crafting", newAttributes[j + i * attribCount]);;
|
|
const int attrib = schematic->getAttribIndex(sid);
|
|
if (attrib == -1)
|
|
{
|
|
// skip over the data for that attrib
|
|
slotIter++;
|
|
const int weightCount = *countIter++;
|
|
weightIter += weightCount * 2;
|
|
continue;
|
|
}
|
|
const int slot = *slotIter++;
|
|
const int weightCount = *countIter++;
|
|
for (int k = 0; k < weightCount; ++k)
|
|
{
|
|
const int resource = *weightIter++;
|
|
const int weight = *weightIter++;
|
|
if (i == 0)
|
|
{
|
|
message->addAssemblyWeight(attrib, slot, resource, weight);
|
|
}
|
|
else
|
|
{
|
|
message->addResourceMaxWeight(attrib, slot, resource, weight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
(safe_cast<ServerController *>(requester.getController()))->appendMessage(
|
|
static_cast<int>(CM_resourceWeights), 0.0f, message,
|
|
GameControllerMessageFlags::SEND |
|
|
GameControllerMessageFlags::RELIABLE |
|
|
GameControllerMessageFlags::DEST_AUTH_CLIENT);
|
|
} // DraftSchematicObject::requestResourceWeights
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Creates a manufacture schematic based on this schematic.
|
|
*
|
|
* @param creator the player creating the schematic
|
|
*
|
|
* @return the manufacture schematic
|
|
*/
|
|
ManufactureSchematicObject * DraftSchematicObject::createManufactureSchematic(
|
|
const CachedNetworkId & creator) const
|
|
{
|
|
Object * object = ServerManufactureSchematicObjectTemplate::createObject(
|
|
"object/manufacture_schematic/generic_schematic.iff", *this);
|
|
if (object == NULL)
|
|
return NULL;
|
|
ManufactureSchematicObject * schematic = safe_cast<ManufactureSchematicObject *>(object);
|
|
schematic->init(*this, creator);
|
|
schematic->setNetworkId(ObjectIdManager::getInstance().getNewObjectId());
|
|
|
|
return schematic;
|
|
} // DraftSchematicObject::createManufactureSchematic
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Gets a draft scrematic slot by name.
|
|
*
|
|
* @param slot slot info to be filled
|
|
* @param name name of the slot to get
|
|
*
|
|
* @return true on success, false if the slot wasn't found
|
|
*/
|
|
bool DraftSchematicObject::getSlot(
|
|
ServerDraftSchematicObjectTemplate::IngredientSlot & slot, int index) const
|
|
{
|
|
if (index < 0 || index >= static_cast<int>((safe_cast<
|
|
const ServerDraftSchematicObjectTemplate*>(
|
|
getObjectTemplate()))->getSlotsCount()))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
slot.options.clear();
|
|
(safe_cast<const ServerDraftSchematicObjectTemplate*>(getObjectTemplate()))->getSlots(slot, index);
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Gets a draft scrematic slot by name.
|
|
*
|
|
* @param slot slot info to be filled
|
|
* @param name name of the slot to get
|
|
*
|
|
* @return true on success, false if the slot wasn't found
|
|
*/
|
|
bool DraftSchematicObject::getSlot(
|
|
ServerDraftSchematicObjectTemplate::IngredientSlot & slot, const StringId & name) const
|
|
{
|
|
NameToIndexMap::const_iterator iter = m_slots.find(name);
|
|
if (iter != m_slots.end())
|
|
return getSlot(slot, (*iter).second);
|
|
return false;
|
|
} // DraftSchematicObject::getSlot(const StringId &)
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Gets the min and max values for an attribute of the schematic.
|
|
*
|
|
* @param index index of the object attribute
|
|
* @param minValue value that will be filled in with the min attribute value
|
|
* @param maxValue value that will be filled in with the max attribute value
|
|
*
|
|
* @return true on success, false if the name is not a valid attribute
|
|
*/
|
|
bool DraftSchematicObject::getAttribMinMax(int index, int & minValue,
|
|
int & maxValue) const
|
|
{
|
|
const SharedDraftSchematicObjectTemplate::SchematicAttribute & minAttrib =
|
|
getAttribMin(index);
|
|
const SharedDraftSchematicObjectTemplate::SchematicAttribute & maxAttrib =
|
|
getAttribMax(index);
|
|
|
|
minValue = minAttrib.value;
|
|
maxValue = maxAttrib.value;
|
|
return true;
|
|
} // DraftSchematicObject::getAttribMinMax(int)
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Gets the min and max values for an attribute of the schematic.
|
|
*
|
|
* @param name the attribute name
|
|
* @param minValue value that will be filled in with the min attribute value
|
|
* @param maxValue value that will be filled in with the max attribute value
|
|
*
|
|
* @return true on success, false if the name is not a valid attribute
|
|
*/
|
|
bool DraftSchematicObject::getAttribMinMax(const StringId & name, int & minValue,
|
|
int & maxValue) const
|
|
{
|
|
NameToIndexMap::const_iterator iter = m_attributes.find(name);
|
|
if (iter == m_slots.end())
|
|
return false;
|
|
|
|
int index = (*iter).second;
|
|
return getAttribMinMax(index, minValue, maxValue);
|
|
} // DraftSchematicObject::getAttribMinMax(const StringId &)
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Returns the name of a experimental attribute associated with an object attribute.
|
|
*
|
|
* @param index index of the object attribute
|
|
*
|
|
* @return the experimental attribute name
|
|
*/
|
|
const StringId DraftSchematicObject::getExperimentalAttributeFromAttribute(
|
|
int index) const
|
|
{
|
|
static const StringId NO_EXPERIMENTATION;
|
|
|
|
const SharedDraftSchematicObjectTemplate::SchematicAttribute & attrib =
|
|
getAttrib(index);
|
|
if (attrib.experiment == NO_EXPERIMENTATION)
|
|
return NO_EXPERIMENTATION;
|
|
|
|
// make sure we can really experiment with the attribute
|
|
int minValue, maxValue;
|
|
if (!getAttribMinMax(index, minValue, maxValue))
|
|
return NO_EXPERIMENTATION;
|
|
|
|
if (minValue == maxValue)
|
|
{
|
|
WARNING(true, ("Draft schematic %s has attribute %s with experimental "
|
|
"attribute %s even though the attribute min/max values are the "
|
|
"same! Not allowing experimentation.", getObjectTemplateName(),
|
|
attrib.name.getCanonicalRepresentation().c_str(),
|
|
attrib.experiment.getCanonicalRepresentation().c_str()));
|
|
return NO_EXPERIMENTATION;
|
|
}
|
|
|
|
return attrib.experiment;
|
|
} // DraftSchematicObject::getExperimentalAttributeFromAttribute
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Returns the name of a experimental attribute associated with an object attribute.
|
|
*
|
|
* @param attribName the object attribute name
|
|
*
|
|
* @return the experimental attribute name
|
|
*/
|
|
const StringId DraftSchematicObject::getExperimentalAttributeFromAttribute(
|
|
const StringId & attribName) const
|
|
{
|
|
static const StringId NO_EXPERIMENTATION;
|
|
|
|
const SharedDraftSchematicObjectTemplate::SchematicAttribute & attrib =
|
|
getAttrib(attribName);
|
|
|
|
if (attrib.experiment == NO_EXPERIMENTATION)
|
|
return NO_EXPERIMENTATION;
|
|
|
|
// make sure we can really experiment with the attribute
|
|
int minValue, maxValue;
|
|
if (!getAttribMinMax(attribName, minValue, maxValue))
|
|
return NO_EXPERIMENTATION;
|
|
|
|
if (minValue == maxValue)
|
|
{
|
|
WARNING(true, ("Draft schematic %s has attribute %s with experimental "
|
|
"attribute %s even though the attribute min/max values are the "
|
|
"same! Not allowing experimentation.", getObjectTemplateName(),
|
|
attrib.name.getCanonicalRepresentation().c_str(),
|
|
attrib.experiment.getCanonicalRepresentation().c_str()));
|
|
return NO_EXPERIMENTATION;
|
|
}
|
|
|
|
return attrib.experiment;
|
|
} // DraftSchematicObject::getExperimentalAttributeFromAttribute
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Returns the names of object attributes associated with an experimental attribute.
|
|
*
|
|
* @param attribName the experimental attribute name
|
|
*
|
|
* @return the object attribute name list
|
|
*/
|
|
const std::vector<StringId> & DraftSchematicObject::getFromAttributeFromExperimentalAttribute(
|
|
const StringId & experimentAttribName) const
|
|
{
|
|
return (*m_experimentalAttributes.find(experimentAttribName)).second;
|
|
} // DraftSchematicObject::getFromAttributeFromExperimentalAttribute
|
|
|
|
|
|
// ======================================================================
|
|
// factory methods
|
|
|
|
/**
|
|
* Returns a draft schematic with a given name. If the schematic isn't loaded,
|
|
* loads it.
|
|
*
|
|
* @param name name of the schematic to load
|
|
*
|
|
* @return the draft schematic
|
|
*/
|
|
const DraftSchematicObject * DraftSchematicObject::getSchematic(
|
|
const std::string & name)
|
|
{
|
|
NOT_NULL(m_schematics);
|
|
return getSchematic(Crc::calculate(name.c_str()));
|
|
} // DraftSchematicObject::getSchematic(const std::string &)
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Returns a draft schematic with a given name. If the schematic isn't loaded,
|
|
* loads it.
|
|
*
|
|
* @param crc crc of name of the schematic to load
|
|
*
|
|
* @return the draft schematic
|
|
*/
|
|
const DraftSchematicObject * DraftSchematicObject::getSchematic(uint32 crc)
|
|
{
|
|
NOT_NULL(m_schematics);
|
|
if (m_schematics == NULL || crc == 0)
|
|
return NULL;
|
|
|
|
// see if the schematic is already loaded
|
|
SchematicMap::iterator result = m_schematics->find(crc);
|
|
if (result != m_schematics->end())
|
|
return (*result).second;
|
|
|
|
// get the template name from the crc
|
|
const ConstCharCrcString & name = ObjectTemplateList::lookUp(crc);
|
|
if (name.isEmpty())
|
|
{
|
|
WARNING(true, ("Unable to find template name for crc %u", crc));
|
|
return NULL;
|
|
}
|
|
|
|
// create a new schematic
|
|
if (!TreeFile::exists(name.getString()))
|
|
{
|
|
WARNING(true, ("Draft schematic template %s file not found", name.getString()));
|
|
return NULL;
|
|
}
|
|
|
|
const ObjectTemplate * objTemplate = ObjectTemplateList::fetch(name);
|
|
if (objTemplate == NULL)
|
|
{
|
|
WARNING(true, ("Can't create object template %s", name.getString()));
|
|
return NULL;
|
|
}
|
|
|
|
const ServerDraftSchematicObjectTemplate * schematicTemplate =
|
|
dynamic_cast<const ServerDraftSchematicObjectTemplate *>(objTemplate);
|
|
if (schematicTemplate == NULL)
|
|
{
|
|
WARNING(true, ("Template %s is not a draft schematic", name.getString()));
|
|
objTemplate->releaseReference();
|
|
return NULL;
|
|
}
|
|
|
|
const DraftSchematicObject * schematic = new DraftSchematicObject(schematicTemplate);
|
|
objTemplate->releaseReference();
|
|
|
|
m_schematics->insert(std::make_pair(crc, schematic));
|
|
return schematic;
|
|
} // DraftSchematicObject::getSchematic(uint32)
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Sets up the draft schematic factory.
|
|
*/
|
|
void DraftSchematicObject::install()
|
|
{
|
|
if (m_schematics == NULL)
|
|
m_schematics = new SchematicMap();
|
|
} // DraftSchematicObject::install
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Cleans up the draft schematic factory
|
|
*/
|
|
void DraftSchematicObject::remove()
|
|
{
|
|
if (m_schematics != NULL)
|
|
{
|
|
SchematicMap::iterator iter;
|
|
for (iter = m_schematics->begin(); iter != m_schematics->end(); ++iter)
|
|
{
|
|
delete (*iter).second;
|
|
(*iter).second = NULL;
|
|
}
|
|
delete m_schematics;
|
|
m_schematics = NULL;
|
|
}
|
|
} // DraftSchematicObject::remove
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void DraftSchematicObject::getAttributes(stdvector<std::pair<std::string, Unicode::String> >::fwd &data) const
|
|
{
|
|
IntangibleObject::getAttributes(data);
|
|
}
|
|
|
|
// ======================================================================
|