Skip to content

脚本执行方式数据库设计和游戏脚本

数据库设计

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'
    }
}