添加示例项目

This commit is contained in:
2026-04-16 16:27:53 +08:00
parent 69a2141804
commit 721fb5a992
192 changed files with 10148 additions and 0 deletions

View File

@@ -0,0 +1,290 @@
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);
}

View File

@@ -0,0 +1,20 @@
{
"提示1": "15代表商店NPC编号[道具ID,限购数量,每月一号刷新,周一刷新,每天上午六点刷新]",
"提示2":"月周日在对应的位置填1代表生效如[2680313, 10, 0, 0, 1]代表道具ID为2680313的道具在15号商店限购10个,每天上午六点刷新",
"提示3":"月周日在对应的位置填1代表生效如[2680313, 10, 0, 1, 0]代表道具ID为2680313的道具在15号商店限购10个,每周一上午六点刷新",
"提示4":"月周日在对应的位置填1代表生效如[2680313, 10, 1, 0, 0]代表道具ID为2680313的道具在15号商店限购10个,每月一号上午六点刷新",
"商店限购配置": {
"15": [
[2680313, 10, 0, 0, 1],
[326211, 10, 0, 0, 1]
],
"16": [
[2680314, 10, 0, 0, 1],
[326211, 10, 0, 0, 1]
]
},
"数据库IP 不是外置数据库不要更改": "127.0.0.1",
"数据库端口 不懂不要更改": 3306,
"数据库用户名 本地用户名不懂不要更改": "game",
"数据库密码 本地密码不懂不要更改": "uu5!^%jg"
}

View File

@@ -0,0 +1,11 @@
{
"ProjectName": "NPC商店限购",
"ProjectDescribe": "指定NPC商店的指定物品的可购买数量可设为每日、每周一、每月1号的上午六点刷新",
"ProjectAuthor": "南瓜",
"ProjectVersion": 1.0,
"ProjectConfig": "NPC商店限购配置_Nangua.json",
"ProjectFiles": [
"NPC商店限购.nut"
],
"ProjectRunFunc": "_Dps_Shop_Limit_Main_"
}