Appearance
cdk方式数据库设计和游戏脚本
数据库设计
sql
数据库表设计
gem_cdk 表
字段 类型 不是null 备注
cdk varchar √ 主键, 非自增
state tinyint √ 有效状态, 1=有效 0=无效
item_id int √ gem_item 表的 id
time varchar 使用 CDK 的时间, 格式 yyyyMMddHHmmss, 这里为什么用 varchar, 因为要方便运维的人, 更直观
character_id int 使用 CDK 的角色 id
gem_item 表 ( cdk 对应的奖励表 )
字段 类型 不是null 备注
id int √ 主键, 自增
type smallint √ 兑换的奖励/道具类型, 1=道具 2=金币 3=点券 4=抵用券... 按需增加
quantity int √ 数量, 金币, 点券, 抵用券等等都有数量
attach varchar 预留给道具或其他, 可以设置道具id, 不是道具一般留空
name varchar 只是为了能记住该奖励的名字
注: 所有 smallint, tinyint 都可以改为 int
----------------------------------------------
数据库表创建语句
注意啊! 注意啊! 注意啊! 表引擎一律用 InnoDB !!! 我干 JAVA 这么多年了, 这圈子能干出来的事最离谱了!
不知道新建表要注意什么, 直接点击 "查询", 下面这是两条 SQL, 直接执行就行
CREATE TABLE `gem_cdk` (
`cdk` varchar(255) NOT NULL,
`state` tinyint(4) NOT NULL,
`item_id` int(255) NOT NULL,
`time` varchar(255) DEFAULT NULL,
`character_id` int(11) DEFAULT NULL,
PRIMARY KEY (`cdk`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `gem_item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` smallint(6) NOT NULL,
`quantity` int(11) NOT NULL,
`attach` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
----------------------------------------------
批量插入 CDK 的 SQL 模板: INSERT INTO gem_cdk(cdk, state, item_id) VALUES('{cdk}', 1, {item_id});
批量删除某一个 item 的所有 CDK: DELETE FROM gem_cdk WHERE item_id = {item_id}
查询某一个 item 的所有 CDK: SELECT * FROM gem_cdk WHERE item_id = {item_id}
游戏脚本
js
/**
* Author: 楠哥
* Contact: 2639068583
* Description: 事务控制, 数据安全, 无超售. 奖励类型支持丰富
* Tip: 使用之前将 conn = cm.getConnection() 改适用于自己服的获取数据库连接的方法
*/
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) {
cm.sendGetText('欢迎光临 宝石商店 \n请输入CDK')
} else if (status == 1) {
var cdk = cm.getText()
try {
useCDK(cdk, 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
}
}, cm.getPlayer().getId())
} catch (e) {
if (e === 101) {
cm.sendOk('卡密已被使用或不存在')
} else {
cm.sendOk('系统错误')
}
}
cm.dispose();
}
}
}
/*
* 兑换奖励
* 异常会抛出错误码, 101: cdk 无效或已被使用
*/
function useCDK(cdk, callback, characterId) {
var conn
var ps
var rs
try {
// conn 是数据库连接的意思, 每个端拿到数据库连接的方式都不太一样
conn = cm.getConnection()
conn.setAutoCommit(false)
// 先查是否有效并获取 item_id
ps = conn.prepareStatement('SELECT item_id FROM gem_cdk WHERE state = 1 AND cdk = ?')
ps.setString(1, cdk)
rs = ps.executeQuery()
if (!rs.next()) {
// cdk 不存在或无效
throw 101
}
var itemId = rs.getInt('item_id')
rs.close()
ps.close()
// 更新 CDK
ps = conn.prepareStatement('UPDATE gem_cdk SET state = 0, character_id = ?, time = ? WHERE cdk = ?')
ps.setInt(1, characterId)
ps.setString(2, getFormattedDateTime())
ps.setString(3, cdk)
if (ps.executeUpdate() == 0) {
throw 1
}
ps.close()
ps = conn.prepareStatement('SELECT type, quantity, `attach` FROM gem_item WHERE id = ?')
ps.setInt(1, itemId)
rs = ps.executeQuery()
rs.next()
// 发奖励啦
callback(rs.getInt('type'), rs.getInt('quantity'), rs.getString('attach'))
rs.close()
ps.close()
conn.setAutoCommit(true)
} catch (e) {
// 回滚
try {
if(conn != null && !conn.isClosed()) {
conn.rollback()
}
} catch (e) {
print(e)
}
// print(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)
}