290 lines
12 KiB
Plaintext
290 lines
12 KiB
Plaintext
g_ShopLimitCache <- {};
|
||
|
||
class _Shop_Limit_Bynangua {
|
||
function get_trade_time() {
|
||
local currentDate = date()
|
||
local year = currentDate.year
|
||
local month = currentDate.month + 1
|
||
local day = currentDate.day
|
||
local hour = currentDate.hour
|
||
local minute = currentDate.min
|
||
local second = currentDate.sec
|
||
return format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||
}
|
||
|
||
// 计算下个月的1号早上6点
|
||
function GetFirstOfNextMonth() {
|
||
local currentDate = date()
|
||
local year = currentDate.year
|
||
local month = currentDate.month + 2 // +2是因为month是从0开始的,且要算下个月
|
||
local day = 1
|
||
local hour = 6
|
||
local minute = 0
|
||
local second = 0
|
||
return format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||
}
|
||
|
||
// 计算下周一早上6点
|
||
function GetNextMonday() {
|
||
local currentDate = date()
|
||
local day = currentDate.wday // 0是周日,1-6是周一到周六
|
||
local diff = (day == 0) ? 1 : (8 - day)
|
||
currentDate.day += diff
|
||
local year = currentDate.year
|
||
local month = currentDate.month + 1
|
||
local day = currentDate.day
|
||
local hour = 6
|
||
local minute = 0
|
||
local second = 0
|
||
return format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||
}
|
||
|
||
// 计算第二天早上6点
|
||
function GetSixAMNextDay() {
|
||
local currentDate = date()
|
||
local year = currentDate.year
|
||
local month = currentDate.month + 1
|
||
local day = currentDate.day + 1
|
||
local hour = 6
|
||
local minute = 0
|
||
local second = 0
|
||
return format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||
}
|
||
|
||
// 获取刷新时间
|
||
function GetRefreshTime(refresh_month, refresh_weeks, refresh_days) {
|
||
if (refresh_month == 1) {
|
||
return GetFirstOfNextMonth()
|
||
} else if (refresh_weeks == 1) {
|
||
return GetNextMonday()
|
||
} else if (refresh_days == 1) {
|
||
return GetSixAMNextDay()
|
||
}
|
||
return null
|
||
}
|
||
|
||
function HandlePurchase(SUser, item_id, item_shop_id, item_info, item_cnt) {
|
||
local charac_no = SUser.GetCID();
|
||
local cache_key = charac_no + "_" + item_id + "_" + item_shop_id;
|
||
|
||
if (g_ShopLimitCache.rawin(cache_key)) {
|
||
local cache_data = g_ShopLimitCache[cache_key];
|
||
local buy_count = cache_data.buy_count;
|
||
local refresh_time = cache_data.refresh_time;
|
||
local current_time = get_trade_time();
|
||
|
||
if (current_time >= refresh_time) {
|
||
if (item_cnt > item_info[1]) {
|
||
SUser.SendNotiPacketMessage("购买失败,可购买数量剩余 " + item_info[1] + " 个", 8);
|
||
return true;
|
||
}
|
||
|
||
local new_refresh_time = GetRefreshTime(item_info[2], item_info[3], item_info[4]);
|
||
g_ShopLimitCache[cache_key] <- {
|
||
buy_count = item_cnt,
|
||
refresh_time = new_refresh_time
|
||
};
|
||
|
||
updateDatabaseAsync(charac_no, item_id, item_shop_id, item_cnt, new_refresh_time);
|
||
} else {
|
||
local remaining = item_info[1] - buy_count;
|
||
if (item_cnt > remaining) {
|
||
if (remaining == 0) {
|
||
local refresh_msg = "";
|
||
if (item_info[2] == 1) { // 月刷新
|
||
refresh_msg = "每月一日上午六点";
|
||
} else if (item_info[3] == 1) { // 周刷新
|
||
refresh_msg = "每周一日上午六点";
|
||
} else if (item_info[4] == 1) { // 日刷新
|
||
refresh_msg = "每日一日上午六点";
|
||
}
|
||
SUser.SendNotiPacketMessage("当前商品已售罄,将在" + refresh_msg + "刷新", 8);
|
||
} else {
|
||
SUser.SendNotiPacketMessage("购买失败,可购买数量剩余 " + remaining + " 个", 8);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
g_ShopLimitCache[cache_key] <- {
|
||
buy_count = buy_count + item_cnt,
|
||
refresh_time = refresh_time
|
||
};
|
||
|
||
updateDatabaseAsync(charac_no, item_id, item_shop_id, buy_count + item_cnt, refresh_time);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
local query = "SELECT id, charac_no, item_id, buy_count, item_shop, refresh_time FROM DP_S.restrict_npc_shop_buy WHERE charac_no=" + charac_no + " AND item_id=" + item_id + " AND item_shop=" + item_shop_id;
|
||
local column_type_list = ["int", "int", "int", "int", "int", "string"];
|
||
local result = SqlObj.Select(query, column_type_list);
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
|
||
if (result.len() == 0) {
|
||
if (item_cnt > item_info[1]) {
|
||
SUser.SendNotiPacketMessage("购买失败,可购买数量剩余 " + item_info[1] + " 个", 8);
|
||
return true;
|
||
}
|
||
|
||
local refresh_time = GetRefreshTime(item_info[2], item_info[3], item_info[4]);
|
||
|
||
g_ShopLimitCache[cache_key] <- {
|
||
buy_count = item_cnt,
|
||
refresh_time = refresh_time
|
||
};
|
||
|
||
updateDatabaseAsync(charac_no, item_id, item_shop_id, item_cnt, refresh_time);
|
||
} else {
|
||
local buy_count = result[0][3];
|
||
local refresh_time = result[0][5];
|
||
local current_time = get_trade_time();
|
||
|
||
g_ShopLimitCache[cache_key] <- {
|
||
buy_count = buy_count,
|
||
refresh_time = refresh_time
|
||
};
|
||
|
||
if (current_time >= refresh_time) {
|
||
if (item_cnt > item_info[1]) {
|
||
SUser.SendNotiPacketMessage("购买失败,可购买数量剩余 " + item_info[1] + " 个", 8);
|
||
return true;
|
||
}
|
||
|
||
local new_refresh_time = GetRefreshTime(item_info[2], item_info[3], item_info[4]);
|
||
g_ShopLimitCache[cache_key] <- {
|
||
buy_count = item_cnt,
|
||
refresh_time = new_refresh_time
|
||
};
|
||
|
||
updateDatabaseAsync(charac_no, item_id, item_shop_id, item_cnt, new_refresh_time);
|
||
} else {
|
||
local remaining = item_info[1] - buy_count;
|
||
if (item_cnt > remaining) {
|
||
if (remaining == 0) {
|
||
local refresh_msg = "";
|
||
if (item_info[2] == 1) { // 月刷新
|
||
refresh_msg = "每月一日上午六点";
|
||
} else if (item_info[3] == 1) { // 周刷新
|
||
refresh_msg = "每周一日上午六点";
|
||
} else if (item_info[4] == 1) { // 日刷新
|
||
refresh_msg = "每日一日上午六点";
|
||
}
|
||
SUser.SendNotiPacketMessage("当前商品已售罄,将在" + refresh_msg + "刷新", 8);
|
||
} else {
|
||
SUser.SendNotiPacketMessage("购买失败,可购买数量剩余 " + remaining + " 个", 8);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
g_ShopLimitCache[cache_key] <- {
|
||
buy_count = buy_count + item_cnt,
|
||
refresh_time = refresh_time
|
||
};
|
||
|
||
updateDatabaseAsync(charac_no, item_id, item_shop_id, buy_count + item_cnt, refresh_time);
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 更新缓存到数据库
|
||
function updateDatabaseAsync(charac_no, item_id, item_shop_id, buy_count, refresh_time) {
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
// 使用 ON DUPLICATE KEY UPDATE 来更新已存在的记录
|
||
local query = "INSERT INTO DP_S.restrict_npc_shop_buy (charac_no, item_id, buy_count, item_shop, refresh_time) " +
|
||
"VALUES (" + charac_no + ", " + item_id + ", " + buy_count + ", " + item_shop_id + ", '" + refresh_time + "') " +
|
||
"ON DUPLICATE KEY UPDATE buy_count = VALUES(buy_count), refresh_time = VALUES(refresh_time)";
|
||
SqlObj.Select(query, []);
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
}
|
||
|
||
// 服务器启动时加载缓存
|
||
function loadShopLimitCache() {
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
local query = "SELECT charac_no, item_id, item_shop, buy_count, refresh_time FROM DP_S.restrict_npc_shop_buy";
|
||
local column_type_list = ["int", "int", "int", "int", "string"];
|
||
local result = SqlObj.Select(query, column_type_list);
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
|
||
foreach(row in result) {
|
||
local cache_key = row[0] + "_" + row[1] + "_" + row[2];
|
||
g_ShopLimitCache[cache_key] <- {
|
||
buy_count = row[3],
|
||
refresh_time = row[4]
|
||
};
|
||
}
|
||
}
|
||
|
||
// 服务器关闭时保存缓存
|
||
Cb_Server_Close_Enter_Func.ShopLimitSave <- function(arg) {
|
||
foreach(cache_key, data in g_ShopLimitCache) {
|
||
local parts = split(cache_key, "_");
|
||
local charac_no = parts[0].tointeger();
|
||
local item_id = parts[1].tointeger();
|
||
local item_shop = parts[2].tointeger();
|
||
updateDatabaseAsync(charac_no, item_id, item_shop, data.buy_count, data.refresh_time);
|
||
}
|
||
g_ShopLimitCache <- {};
|
||
}
|
||
|
||
function _Dps_Shop_Limit_Main_() {
|
||
CreateShopLimitTable();
|
||
loadShopLimitCache();
|
||
Cb_BuyItem_check_error_Leave_Func.Shop_Limit_ByNangua <- function(args) {
|
||
local Config = GlobalConfig.Get("NPC商店限购配置_Nangua.json");
|
||
local shop_limit_config = Config["商店限购配置"];
|
||
local is_buy = false;
|
||
local SUser = User(args[1]);
|
||
local msg_base = args[2];
|
||
local Item_id = NativePointer(msg_base).add(13).readU32();
|
||
local item_shop = NativePointer(msg_base).add(21).readU32();
|
||
local item_cnt = NativePointer(msg_base).add(17).readU32();
|
||
local item_shop_id = item_shop.tostring();
|
||
if (item_shop_id in shop_limit_config) {
|
||
local items_list = shop_limit_config[item_shop_id];
|
||
foreach(item_info in items_list) {
|
||
if (item_info[0] == Item_id) {
|
||
is_buy = _Shop_Limit_Bynangua.HandlePurchase(SUser, Item_id, item_shop, item_info, item_cnt);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (is_buy) {
|
||
return 19;
|
||
}
|
||
}
|
||
}
|
||
|
||
function CreateShopLimitTable() {
|
||
local Config = GlobalConfig.Get("NPC商店限购配置_Nangua.json");
|
||
local PoolObj = MysqlPool.GetInstance();
|
||
local Ip = Config["数据库IP 不是外置数据库不要更改"];
|
||
local Port = Config["数据库端口 不懂不要更改"];
|
||
local DbName = Config["数据库用户名 本地用户名不懂不要更改"];
|
||
local Password = Config["数据库密码 本地密码不懂不要更改"];
|
||
|
||
PoolObj.SetBaseConfiguration(Ip, Port, DbName, Password);
|
||
PoolObj.PoolSize = 10;
|
||
PoolObj.Init();
|
||
|
||
// 建库建表SQL
|
||
local CreateSql1 = "create database if not exists DP_S default charset utf8;";
|
||
local CreateSql2 = "CREATE TABLE IF NOT EXISTS DP_S.restrict_npc_shop_buy (" +
|
||
"id int(11) AUTO_INCREMENT, " +
|
||
"charac_no int(11) NOT NULL, " +
|
||
"item_id int(11) NOT NULL, " +
|
||
"buy_count int(11) NOT NULL, " +
|
||
"item_shop int(11) NOT NULL, " +
|
||
"refresh_time varchar(255) NOT NULL, " +
|
||
"PRIMARY KEY (id), " +
|
||
"UNIQUE KEY unique_purchase (charac_no, item_id, item_shop)" +
|
||
") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
|
||
|
||
// 执行SQL
|
||
local SqlObj = MysqlPool.GetInstance().GetConnect();
|
||
SqlObj.Exec_Sql(CreateSql1);
|
||
SqlObj.Exec_Sql(CreateSql2);
|
||
MysqlPool.GetInstance().PutConnect(SqlObj);
|
||
} |