summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/manaserv.xml.example11
-rw-r--r--src/account-server/accounthandler.cpp135
-rw-r--r--src/protocol.h2
3 files changed, 95 insertions, 53 deletions
diff --git a/docs/manaserv.xml.example b/docs/manaserv.xml.example
index d41b298..a04b57e 100644
--- a/docs/manaserv.xml.example
+++ b/docs/manaserv.xml.example
@@ -1,19 +1,19 @@
<?xml version="1.0"?>
<!--
An example configuration file.
-
+
Documentation: http://doc.manasource.org/manaserv.xml
Developers: If you add any new parameters read from this configuration file
don't forget to update the wiki documentation!
-->
<configuration>
-
+
<!-- Database configuration ***************************************************
Uncomment one of the following parts according to the database backend you
would like to use.
-->
-
+
<!--
SQLite specific configuration.
@@ -119,7 +119,6 @@
<option name="char_minNameLength" value="4" />
<option name="char_maxNameLength" value="25" />
<option name="char_maxCharacters" value="3" />
- <option name="char_startingPoints" value="60" />
<!-- Chat-related config options -->
<option name="chat_maxChannelNameLength" value="15" />
@@ -134,6 +133,6 @@
<!-- Mail-system related-->
<option name="mail_maxAttachments" value="3" />
<option name="mail_maxLetters" value="10" />
-
-
+
+
</configuration>
diff --git a/src/account-server/accounthandler.cpp b/src/account-server/accounthandler.cpp
index 9008d26..1342b36 100644
--- a/src/account-server/accounthandler.cpp
+++ b/src/account-server/accounthandler.cpp
@@ -52,8 +52,10 @@ static void addUpdateHost(MessageOut *msg)
// List of attributes that the client can send at account creation.
+static std::vector< int > initAttr;
-static std::vector< unsigned int > initAttr;
+// Character's starting points
+static int startPoints, attributesMinimum, attributesMaximum = 0;
/*
* Map attribute ids to values that they need to be initialised to at account
@@ -61,7 +63,6 @@ static std::vector< unsigned int > initAttr;
* The pair contains two elements of the same value (the default) so that the
* iterators can be used to copy a range.
*/
-
static std::map< unsigned int, std::pair< double, double> > defAttr;
class AccountHandler : public ConnectionHandler
@@ -130,45 +131,88 @@ static AccountHandler *accountHandler;
AccountHandler::AccountHandler(const std::string &attrFile):
mTokenCollector(this)
{
- // Probably not the best place for this, but I don't have a lot of time.
- if (initAttr.empty())
- {
- std::string absPathFile;
- xmlNodePtr node;
+ // In case of reloading...
+ initAttr.clear();
- absPathFile = ResourceManager::resolve(attrFile);
- if (absPathFile.empty()) {
- LOG_FATAL("Account handler: Could not find " << attrFile << "!");
- exit(3);
- return;
- }
+ std::string absPathFile = ResourceManager::resolve(attrFile);
+ if (absPathFile.empty())
+ {
+ LOG_FATAL("Account handler: Could not find " << attrFile << "!");
+ exit(3);
+ }
- XML::Document doc(absPathFile, int());
- node = doc.rootNode();
+ XML::Document doc(absPathFile, int());
+ xmlNodePtr node = doc.rootNode();
+ if (!node || !xmlStrEqual(node->name, BAD_CAST "attributes"))
+ {
+ LOG_FATAL("Account handler: " << attrFile << ": "
+ << " is not a valid database file!");
+ exit(3);
+ }
- if (!node || !xmlStrEqual(node->name, BAD_CAST "attributes"))
+ for_each_xml_child_node(attributenode, node)
+ {
+ if (xmlStrEqual(attributenode->name, BAD_CAST "attribute"))
{
- LOG_FATAL("Account handler: " << attrFile
- << " is not a valid database file!");
- exit(3);
- return;
+ int id = XML::getProperty(attributenode, "id", 0);
+ if (!id)
+ {
+ LOG_WARN("Account handler: " << attrFile << ": "
+ << "An invalid attribute id value (0) has been found "
+ << "and will be ignored.");
+ continue;
+ }
+
+ if (utils::toupper(XML::getProperty(attributenode, "modifiable", "false")) == "TRUE")
+ initAttr.push_back(id);
+
+ // Store as string initially to check
+ // that the property is defined.
+ std::string defStr = XML::getProperty(attributenode, "default", "");
+ if (!defStr.empty())
+ {
+ double val = string_to<double>()(defStr);
+ defAttr.insert(std::make_pair(id,std::make_pair(val, val)));
+ }
}
- for_each_xml_child_node(attributenode, node)
- if (xmlStrEqual(attributenode->name, BAD_CAST "attribute"))
+ else if (xmlStrEqual(attributenode->name, BAD_CAST "points"))
+ {
+ startPoints = XML::getProperty(attributenode, "start", 0);
+ attributesMinimum = XML::getProperty(attributenode, "minimum", 0);
+ attributesMaximum = XML::getProperty(attributenode, "maximum", 0);
+
+ // Stops if not all the values are given.
+ if (!startPoints || !attributesMinimum || !attributesMaximum)
{
- unsigned int id = XML::getProperty(attributenode, "id", 0);
- if (!id) continue;
- if (utils::toupper(XML::getProperty(attributenode, "modifiable", "false")) == "TRUE")
- initAttr.push_back(id);
- // Store as string initially to check that the property is defined.
- std::string defStr = XML::getProperty(attributenode, "default", "");
- if (!defStr.empty())
- {
- double val = string_to<double>()(defStr);
- defAttr.insert(std::make_pair(id, std::make_pair(val, val)));
- }
+ LOG_FATAL("Account handler: " << attrFile << ": "
+ << " The characters starting points "
+ << "are incomplete or not set!");
+ exit(3);
}
+ }
+ } // End for each XML nodes
+
+ // Sanity checks on attributes.
+ if (initAttr.empty())
+ {
+ LOG_FATAL("Account handler: " << attrFile << ": "
+ << "No modifiable attributes found!");
+ exit(3);
+ }
+
+ // Sanity checks on starting points.
+ int modifiableAttributeCount = (int) initAttr.size();
+ if (modifiableAttributeCount * attributesMaximum < startPoints ||
+ modifiableAttributeCount * attributesMinimum > startPoints)
+ {
+ LOG_FATAL("Account handler: " << attrFile << ": "
+ << "Character's point values make "
+ << "the character's creation impossible!");
+ exit(3);
}
+
+ LOG_DEBUG("Character start points: " << startPoints << " (Min: "
+ << attributesMinimum << ", Max: " << attributesMaximum << ")");
}
bool AccountClientHandler::initialize(const std::string &configFile, int port,
@@ -621,8 +665,6 @@ void AccountHandler::handleCharacterCreateMessage(AccountClient &client, Message
unsigned int minNameLength = Configuration::getValue("char_minNameLength", 4);
unsigned int maxNameLength = Configuration::getValue("char_maxNameLength", 25);
unsigned int maxCharacters = Configuration::getValue("char_maxCharacters", 3);
- unsigned int startingPoints = Configuration::getValue("char_startingPoints", 60);
-
MessageOut reply(APMSG_CHAR_CREATE_RESPONSE);
@@ -677,33 +719,34 @@ void AccountHandler::handleCharacterCreateMessage(AccountClient &client, Message
// LATER_ON: Add race, face and maybe special attributes.
// Customization of character's attributes...
- std::vector< unsigned int > attributes = std::vector<unsigned int>(initAttr.size(), 0);
+ std::vector<int> attributes = std::vector<int>(initAttr.size(), 0);
for (unsigned int i = 0; i < initAttr.size(); ++i)
attributes[i] = msg.readShort();
- unsigned int totalAttributes = 0;
- bool validNonZeroAttributes = true;
+ int totalAttributes = 0;
for (unsigned int i = 0; i < initAttr.size(); ++i)
{
// For good total attributes check.
totalAttributes += attributes.at(i);
- // For checking if all stats are at least > 0
- if (attributes[i] <= 0) validNonZeroAttributes = false;
+ // For checking if all stats are >= min and <= max.
+ if (attributes.at(i) < attributesMinimum
+ || attributes.at(i) > attributesMaximum)
+ {
+ reply.writeByte(CREATE_ATTRIBUTES_OUT_OF_RANGE);
+ client.send(reply);
+ return;
+ }
}
- if (totalAttributes > startingPoints)
+ if (totalAttributes > startPoints)
{
reply.writeByte(CREATE_ATTRIBUTES_TOO_HIGH);
}
- else if (totalAttributes < startingPoints)
+ else if (totalAttributes < startPoints)
{
reply.writeByte(CREATE_ATTRIBUTES_TOO_LOW);
}
- else if (!validNonZeroAttributes)
- {
- reply.writeByte(CREATE_ATTRIBUTES_EQUAL_TO_ZERO);
- }
else
{
Character *newCharacter = new Character(name);
diff --git a/src/protocol.h b/src/protocol.h
index 9b5c16f..2a2c6bd 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -305,7 +305,7 @@ enum {
CREATE_INVALID_GENDER,
CREATE_ATTRIBUTES_TOO_HIGH,
CREATE_ATTRIBUTES_TOO_LOW,
- CREATE_ATTRIBUTES_EQUAL_TO_ZERO,
+ CREATE_ATTRIBUTES_OUT_OF_RANGE,
CREATE_EXISTS_NAME,
CREATE_TOO_MUCH_CHARACTERS
};