Merge pull request #549 from KinglyKrab/master

Fixed quantity in merchant purchase.
This commit is contained in:
Akkadius 2016-08-27 16:59:58 -05:00 committed by GitHub
commit 5c43f2d80e
15 changed files with 97 additions and 66 deletions

View File

@ -1,5 +1,11 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 08/27/2016 ==
Kinglykrab: Added optional IP-based account exemptions.
- To use this system simply set World:EnableIPExemptions to true and create an entry in the ip_exemptions table.
- Example: exemption_ip of IP 192.168.1.4 in ip_exemptions with exemption_amount of 1 will allow only 1 account to login from IP 192.168.1.4.
- Note: If there is no exemption, the amount of accounts logged in from a singular IP will default to World:MaxClientsPerIP
== 08/23/2016 ==
noudess: Force mobs on a depop @ end pathgrid to still do this on idle zones.
This makes them be more random after a zone is idle, rather than always showing

View File

@ -2136,3 +2136,15 @@ bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year
return results.Success();
}
int Database::GetIPExemption(std::string account_ip) {
std::string query = StringFormat("SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '%s'", account_ip.c_str());
auto results = QueryDatabase(query);
if (results.Success() && results.RowCount() > 0) {
auto row = results.begin();
return atoi(row[0]);
}
return RuleI(World, MaxClientsPerIP);
}

View File

@ -186,6 +186,8 @@ public:
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 acctid);
int GetIPExemption(std::string account_ip);
/* Groups */

View File

@ -1934,8 +1934,7 @@ struct Merchant_Sell_Struct {
/*004*/ uint32 playerid; // Player's entity id
/*008*/ uint32 itemslot;
uint32 unknown12;
/*016*/ uint8 quantity; // Already sold
/*017*/ uint8 Unknown016[3];
/*016*/ uint32 quantity;
/*020*/ uint32 price;
};
struct Merchant_Purchase_Struct {

View File

@ -83,6 +83,7 @@ namespace Logs {
Server_Client_Packet_With_Dump,
Client_Server_Packet_With_Dump,
Login_Server,
Client_Login,
MaxCategoryID /* Don't Remove this*/
};
@ -131,7 +132,8 @@ namespace Logs {
"Packet :: Client -> Server Unhandled",
"Packet :: Server -> Client (Dump)",
"Packet :: Client -> Server (Dump)",
"Login Server"
"Login Server",
"Client Login"
};
}

View File

@ -1880,8 +1880,7 @@ struct Merchant_Sell_Struct {
/*004*/ uint32 playerid; // Player's entity id
/*008*/ uint32 itemslot;
/*012*/ uint32 unknown12;
/*016*/ uint8 quantity; // Already sold
/*017*/ uint8 Unknown017[3];
/*016*/ uint32 quantity;
/*020*/ uint32 Unknown020;
/*024*/ uint32 price;
/*028*/ uint32 pricehighorderbits; // It appears the price is 64 bits in SoD+

View File

@ -1859,8 +1859,7 @@ struct Merchant_Sell_Struct {
/*004*/ uint32 playerid; // Player's entity id
/*008*/ uint32 itemslot;
uint32 unknown12;
/*016*/ uint8 quantity; // Already sold
/*017*/ uint8 Unknown016[3];
/*016*/ uint32 quantity;
/*020*/ uint32 price;
};
struct Merchant_Purchase_Struct {

View File

@ -1657,8 +1657,7 @@ struct Merchant_Sell_Struct {
/*004*/ uint32 playerid; // Player's entity id
/*008*/ uint32 itemslot;
uint32 unknown12;
/*016*/ uint8 quantity; // Already sold
/*017*/ uint8 Unknown016[3];
/*016*/ uint32 quantity;
/*020*/ uint32 price;
};
struct Merchant_Purchase_Struct {

View File

@ -1921,8 +1921,7 @@ struct Merchant_Sell_Struct {
/*004*/ uint32 playerid; // Player's entity id
/*008*/ uint32 itemslot;
/*012*/ uint32 unknown12;
/*016*/ uint8 quantity; // Already sold
/*017*/ uint8 Unknown017[3];
/*016*/ uint32 quantity;
/*020*/ uint32 Unknown020;
/*024*/ uint32 price;
/*028*/ uint32 pricehighorderbits; // It appears the price is 64 bits in Underfoot+

View File

@ -205,6 +205,7 @@ RULE_INT(World, ExemptMaxClientsStatus, -1) // Exempt accounts from the MaxClien
RULE_INT(World, AddMaxClientsPerIP, -1) // Maximum number of clients allowed to connect per IP address if account status is < ExemptMaxClientsStatus. Default value: -1 (feature disabled)
RULE_INT(World, AddMaxClientsStatus, -1) // Accounts with status >= this rule will be allowed to use the amount of accounts defined in the AddMaxClientsPerIP. Default value: -1 (feature disabled)
RULE_BOOL(World, MaxClientsSetByStatus, false) // If True, IP Limiting will be set to the status on the account as long as the status is > MaxClientsPerIP
RULE_BOOL(World, EnableIPExemptions, false) // If True, ip_exemptions table is used, if there is no entry for the IP it will default to RuleI(World, MaxClientsPerIP)
RULE_BOOL(World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots.
RULE_BOOL(World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks.
RULE_INT(World, AccountSessionLimit, -1) //Max number of characters allowed on at once from a single account (-1 is disabled)

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9098
#define CURRENT_BINARY_DATABASE_VERSION 9099
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008
#else

View File

@ -352,6 +352,7 @@
9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty|
9097|2016_07_03_npc_class_as_last_name.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'NPC:UseClassAsLastName'|empty|
9098|2016_08_26_object_size_tilt.sql|SHOW COLUMNS FROM `object` LIKE 'size'|empty|
9099|2016_08_27_ip_exemptions.sql|SHOW TABLES LIKE 'ip_exemptions'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,14 @@
-- IP Exemptions table structure
DROP TABLE IF EXISTS `ip_exemptions`;
CREATE TABLE `ip_exemptions` (
`exemption_id` int(11) NOT NULL AUTO_INCREMENT,
`exemption_ip` varchar(255) DEFAULT NULL,
`exemption_amount` int(11) DEFAULT NULL,
PRIMARY KEY (`exemption_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
-- Rule Value Entry, Default to false
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES ('1', 'World:EnableIPExemptions', 'true', 'notation');
-- Logging Category Entry
INSERT INTO `logsys_categories` (`log_category_id`, `log_category_description`, `log_to_console`, `log_to_file`, `log_to_gmsay`) VALUES ('44', 'Client Login', '1', '1', '1');

View File

@ -722,7 +722,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
return true;
}
if (RuleI(World, MaxClientsPerIP) >= 0) {
if (RuleB(World, EnableIPExemptions) || RuleI(World, MaxClientsPerIP) >= 0) {
client_list.GetCLEIP(this->GetIP()); //Check current CLE Entry IPs against incoming connection
}

View File

@ -29,6 +29,7 @@
#include "../common/classes.h"
#include "../common/packet_dump.h"
#include "wguild_mgr.h"
#include "../common/misc.h"
#include <set>
@ -142,7 +143,6 @@ void ClientList::EnforceSessionLimit(uint32 iLSAccountID) {
//Check current CLE Entry IPs against incoming connection
void ClientList::GetCLEIP(uint32 iIP) {
ClientListEntry* countCLEIPs = 0;
LinkedListIterator<ClientListEntry*> iterator(clientlist);
@ -150,64 +150,62 @@ void ClientList::GetCLEIP(uint32 iIP) {
iterator.Reset();
while(iterator.MoreElements()) {
countCLEIPs = iterator.GetData();
// If the IP matches, and the connection admin status is below the exempt status,
// or exempt status is less than 0 (no-one is exempt)
if ((countCLEIPs->GetIP() == iIP) &&
((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) ||
(RuleI(World, ExemptMaxClientsStatus) < 0))) {
// Increment the occurences of this IP address
IPInstances++;
// If the number of connections exceeds the lower limit
if (IPInstances > (RuleI(World, MaxClientsPerIP))) {
// If MaxClientsSetByStatus is set to True, override other IP Limit Rules
if (RuleB(World, MaxClientsSetByStatus)) {
// The IP Limit is set by the status of the account if status > MaxClientsPerIP
if (IPInstances > countCLEIPs->Admin()) {
if(RuleB(World, IPLimitDisconnectAll)) {
countCLEIPs = iterator.GetData();
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0))) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt)
IPInstances++; // Increment the occurences of this IP address
Log.Out(Logs::General, Logs::Client_Login, "Account ID: %i Account Name: %s IP: %s.", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
if (RuleB(World, EnableIPExemptions)) {
Log.Out(Logs::General, Logs::Client_Login, "Account ID: %i Account Name: %s IP: %s IP Instances: %i Max IP Instances: %i", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str(), IPInstances, database.GetIPExemption(long2ip(countCLEIPs->GetIP()).c_str()));
if (IPInstances > database.GetIPExemption(long2ip(countCLEIPs->GetIP()).c_str())) {
if(RuleB(World, IPLimitDisconnectAll)) {
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str());
DisconnectByIP(iIP);
return;
} else {
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline);
iterator.RemoveCurrent();
continue;
}
}
} else {
if (IPInstances > (RuleI(World, MaxClientsPerIP))) { // If the number of connections exceeds the lower limit
if (RuleB(World, MaxClientsSetByStatus)) { // If MaxClientsSetByStatus is set to True, override other IP Limit Rules
Log.Out(Logs::General, Logs::Client_Login, "Account ID: %i Account Name: %s IP: %s IP Instances: %i Max IP Instances: %i", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str(), IPInstances, countCLEIPs->Admin());
if (IPInstances > countCLEIPs->Admin()) { // The IP Limit is set by the status of the account if status > MaxClientsPerIP
if(RuleB(World, IPLimitDisconnectAll)) {
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str());
DisconnectByIP(iIP);
return;
} else {
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
iterator.RemoveCurrent();
continue;
}
}
} else if ((countCLEIPs->Admin() < RuleI(World, AddMaxClientsStatus)) || (RuleI(World, AddMaxClientsStatus) < 0)) { // Else if the Admin status of the connection is not eligible for the higher limit, or there is no higher limit (AddMaxClientStatus < 0)
if(RuleB(World, IPLimitDisconnectAll)) {
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str());
DisconnectByIP(iIP);
return;
} else {
// Remove the connection
countCLEIPs->SetOnline(CLE_Status_Offline);
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
iterator.RemoveCurrent();
continue;
}
} else if (IPInstances > RuleI(World, AddMaxClientsPerIP)) { // else they are eligible for the higher limit, but if they exceed that
if(RuleB(World, IPLimitDisconnectAll)) {
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str());
DisconnectByIP(iIP);
return;
} else {
Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
iterator.RemoveCurrent();
continue;
}
}
}
// Else if the Admin status of the connection is not eligible for the higher limit,
// or there is no higher limit (AddMaxClientStatus<0)
else if ((countCLEIPs->Admin() < (RuleI(World, AddMaxClientsStatus)) ||
(RuleI(World, AddMaxClientsStatus) < 0))) {
if(RuleB(World, IPLimitDisconnectAll)) {
DisconnectByIP(iIP);
return;
} else {
// Remove the connection
countCLEIPs->SetOnline(CLE_Status_Offline);
iterator.RemoveCurrent();
continue;
}
}
// else they are eligible for the higher limit, but if they exceed that
else if (IPInstances > RuleI(World, AddMaxClientsPerIP)) {
if(RuleB(World, IPLimitDisconnectAll)) {
DisconnectByIP(iIP);
return;
} else {
// Remove the connection
countCLEIPs->SetOnline(CLE_Status_Offline);
iterator.RemoveCurrent();
continue;
}
}
}