Appearance
脚本执行方式数据库设计和游戏脚本
数据库设计
sql
数据库表设计
gem_warehouse 表 ( 仓库表 )
字段 类型 不是null 备注
id int √ 主键, 自增
qq varchar √ qq, 只要账号绑定了此 qq 才能领取
type smallint √ 兑换的奖励/道具类型, 1=道具 2=金币 3=点券 4=抵用券... 按需增加
quantity int √ 数量, 金币, 点券, 抵用券等等都有数量
attach varchar 预留给道具或其他, 可以设置道具id, 不是道具一般留空
----------------------------------------------
CREATE TABLE `gem_warehouse` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`qq` varchar(15) NOT NULL,
`type` smallint(6) NOT NULL,
`quantity` int(11) NOT NULL,
`attach` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
游戏脚本
js
/**
* Author: 楠哥
* Contact: 2639068583
* Description: 事务控制, 数据安全, 无超售. 奖励类型支持丰富
* Tip: 使用之前将 conn = cm.getConnection() 改适用于自己服的获取数据库连接的方法
*/
var list = []
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (status >= 0 && mode == 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (status == 0) {
list = getWarehouse(getName(cm.getPlayer().getAccountID()))
var txt = '你在Q群#e[宝石商店]#n购买的商品待领取\r\n该功能绑定QQ号之后才能用哦'
if (list.length != 0) {
for (var i = 0; i < list.length; i++) {
txt += '\r\n#L' + (i + 1) + '##v' + list[i].attach + '##z' + list[i].attach + '# x ' + list[i].quantity + '#l'
}
} else {
txt += '\r\n#e空空如也'
}
cm.sendOk(txt)
} else if (status == 1) {
// 空空如也
if (selection < 0) {
status = 9999
return;
}
try {
receive(list[selection - 1].id, function(type, quantity, attach) {
if (type == 1) {
// 注意检查背包剩余可用格数, 拿到 id 可以用 xml 获得装备名字, 也可以提前写到数据库里
cm.sendOk('获得 #v' + attach + '##z' + attach + '# x ' + quantity)
cm.gainItem(parseInt(attach), quantity)
} else if (type == 2) {
// 给金币
cm.sendOk('获得 ' + quantity + ' 金币')
cm.gainMeso(quantity)
} else if (type == 3) {
// 给点券
cm.sendOk('获得 ' + quantity + ' 点券')
cm.gainNX(quantity)
} else if (type == 4) {
// 给抵用券
cm.sendOk('获得 ' + quantity + ' 抵用券')
cm.gainDY(quantity)
} else {
throw 102
}
})
status = -1
} catch (e) {
// print(e.stack)
cm.sendOk('系统错误')
}
} else {
cm.dispose();
}
}
}
/**
* 领取
* @param characterId
* @param warehouse_id
* @param callback
*/
function receive(warehouse_id, callback) {
var conn
var ps
var rs
try {
// conn 是数据库连接的意思, 每个端拿到数据库连接的方式都不太一样
conn = cm.getConnection()
conn.setAutoCommit(false)
ps = conn.prepareStatement('SELECT * FROM gem_warehouse WHERE id = ?')
ps.setInt(1, warehouse_id)
rs = ps.executeQuery()
rs.next()
var type = rs.getInt('type')
var quantity = rs.getInt('quantity')
var attach = rs.getString('attach')
rs.close()
ps.close()
ps = conn.prepareStatement('DELETE FROM gem_warehouse WHERE id = ?')
ps.setInt(1, warehouse_id)
if (ps.executeUpdate() == 0) {
throw 1
}
callback(type, quantity, attach)
} catch (e) {
// 回滚
try {
if(conn != null && !conn.isClosed()) {
conn.rollback()
}
} catch (e) {
print(e)
}
// print(e)
throw e
throw e
} finally {
try {
if (rs != null) {
rs.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (ps != null) {
ps.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (conn != null && !conn.isClosed()) {
conn.setAutoCommit(true)
conn.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
}
}
/**
* 获取仓库物品
* @param qq
* @returns {*[]}
*/
function getWarehouse(qq) {
var conn
var ps
var rs
try {
// conn 是数据库连接的意思, 每个端拿到数据库连接的方式都不太一样
conn = cm.getConnection()
// 先查是否有效并获取 item_id
ps = conn.prepareStatement('SELECT * FROM gem_warehouse WHERE qq = ?')
ps.setString(1, qq)
rs = ps.executeQuery()
var list = []
while (rs.next()) {
list.push({
id: rs.getInt('id'),
type: rs.getInt('type'),
quantity: rs.getInt('quantity'),
attach: rs.getString('attach')
})
}
return list
} catch (e) {
throw e
} finally {
try {
if (rs != null) {
rs.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (ps != null) {
ps.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (conn != null && !conn.isClosed()) {
conn.setAutoCommit(true)
conn.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
}
}
// 获取格式化的时间
function getFormattedDateTime() {
var now = new Date()
var year = now.getFullYear()
var month = now.getMonth() + 1
var day = now.getDate()
var hours = now.getHours()
var minutes = now.getMinutes()
var seconds = now.getSeconds()
return '' + year + (month > 9 ? month : '0' + month)
+ (day > 9 ? day : '0' + day)
+ (hours > 9 ? hours : '0' + hours)
+ (minutes > 9 ? minutes : '0' + minutes)
+ (seconds > 9 ? seconds : '0' + seconds)
}
/**
* 获取账号名
* @param qq
* @returns {*[]}
*/
function getName(cid) {
var conn
var ps
var rs
try {
// conn 是数据库连接的意思, 每个端拿到数据库连接的方式都不太一样
conn = cm.getConnection()
ps = conn.prepareStatement('SELECT name FROM accounts WHERE id = ?')
ps.setInt(1, cid)
rs = ps.executeQuery()
rs.next()
return rs.getString('name')
} catch (e) {
throw e
} finally {
try {
if (rs != null) {
rs.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (ps != null) {
ps.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (conn != null && !conn.isClosed()) {
conn.setAutoCommit(true)
conn.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
}
}
/**
* 获取 qq 号
* @param accountId
* @returns {*[]}
*/
function getQQ(aid) {
var conn
var ps
var rs
try {
// conn 是数据库连接的意思, 每个端拿到数据库连接的方式都不太一样
conn = cm.getConnection()
ps = conn.prepareStatement('SELECT qq FROM accounts WHERE id = ?')
ps.setInt(1, aid)
rs = ps.executeQuery()
rs.next()
return rs.getString('qq')
} catch (e) {
throw e
} finally {
try {
if (rs != null) {
rs.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (ps != null) {
ps.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
try {
if (conn != null && !conn.isClosed()) {
conn.setAutoCommit(true)
conn.close()
}
} catch (e) {
print(e)
// e.printStackTrace()
}
}
}
机器人脚本
js
/**
* 此功能是为了实现, 购买商品直接放到数据库中, 玩家点击 NPC 即可领取
* 免去维护 CDK 的烦恼
* 前提:
* 你的游戏中已经实现了, 基于 QQ 的共享仓库, 并且账号绑定了 QQ
* 为什么说是共享仓库呢, 因为 1 个 QQ 可以绑定多个游戏账号
*/
const mxdb = require('mxdb')
const items = {
'9': ['道具', 100, '2000005'],
'10': ['道具', 1, '2340000']
}
/**
* 发货
* @param event event.userId 即使 QQ
* @param cdk 弃用
* @param id 商品 id
* @returns result
* 返回 string 且非空, 发货成功, 并使用返回值代替系统的发货提示
* 返回 false 发货失败, 库存数据库进行回滚
* 返回 其他类型 发货成功, 使用系统发货提示
* 抛出异常, 发货失败
* 总结: 只有返回 false 发货失败
*/
exports.action = function (event, cdk, id) {
const item = items[String(id)]
entryWarehouse(event.userId, item[0], item[1], item[2])
return '购买成功, 请前往[射手村]-[快递员 杜宜]领取'
}
/**
* 入库
* 1=道具 2=金币 3=点券 4=抵用券... 按需增加
*/
function entryWarehouse(userId, type, quantity, itemId) {
if (typeof type === 'string') {
if (type === '道具') {
type = 1
} else if (type === '金币') {
type = 2
} else if (type === '点券') {
type = 3
} else if (type === '抵用券') {
type = 4
}
}
let rows
if (itemId) {
rows = mxdb.update('INSERT INTO gem_warehouse(qq, type, quantity, attach) VALUES(?, ?, ?, ?)', userId, type, quantity, itemId)
} else {
rows = mxdb.update('INSERT INTO gem_warehouse(qq, type, quantity) VALUES(?, ?, ?)', userId, type, quantity)
}
if (rows == 0) {
throw 'Entry warehouse failed'
}
}