用户:
幻想一笑而过查看:4 回复:20 评论:4 创建时间:2021-07-31T22:05:17
话不多说,直接上代码
//签到-----------------------------------------------------------------------------
(async function () {
createTable5()
})();
async function loadPlayer_(entity) { // 导入玩家SQL得分到地图玩家变量
//用poll确保在数据库短暂掉线后还能继续执行这个sql语句.
//userKey包含大写字母, 需要用""包住
//右边记得加上 ) 匹配左边的 poll(
const data = (await poll(() => db.sql`SELECT * FROM "playersign" WHERE name=${entity.player.name}`))[0]
if (data) {
entity.player.signtime = data.signtime
}
};
world.onPlayerJoin(({ entity }) => {
entity.player.signtime = 0
loadPlayer_(entity)
})
async function createTable5() {
//一直轮询等待"SELECT 1"执行成功, 这是最简单的测试数据库是否在线的语句
await poll(() => db.sql`SELECT 1`, '等待玩家签到pg数据库启动中...')
world.say('玩家签到pg数据库启动完毕')
await db.sql`CREATE TABLE IF NOT EXISTS "playersign" (
name VARCHAR(50) NOT NULL,
"signtime" VARCHAR(50) NOT NULL
)`
}
// 第一次进入游戏时,新建玩家数据
async function insertPlayer__(name, sign) {
try {
await poll(() => db.sql`INSERT INTO "playersign" VALUES (${name}, ${sign})`);
} catch (e) {
console.log(`insert sql error: ${e}`, name, sign);
}
}
// 更新玩家进入游戏时间
async function updatePlayerJoin_(name, value) {
try {
await poll(() => db.sql`UPDATE "playersign" SET "signtime" = ${value} WHERE name = ${name}`);
} catch (e) {
console.log(`[jointime] update sql error: ${e}`);
}
}
// 查询数据。如果数据不存在,返回空。
async function getPlayerData_(name) {
const rows = (await poll(() => db.sql`SELECT * FROM "playersign" WHERE name=${name}`));
if (rows && !rows.length) {
return null;
}
return rows[0];
}
// 清空所有数据
async function clearsign_() {
await db.sql`DELETE FROM "playersign"`
world.say(`清空所有签到数据!`);
}
//今天的时间
//拼接时间
function show() {
var str = "今天的时间是:" + today;
return str;
}
async function poll(fn, msg) {//无限轮询执行sql语句直到成功
while (true) {
try {
return await fn()//一旦成功执行, 停止无限轮询, 并返回查询结果
} catch (e) {
const m = e.message//需要简略显示的异常消息
//sql偶尔会执行超时, 但如果反复显示timeout 15秒以上一直不停, 请通知官方人员
//第一次运行时, 由于玩家在数据表创建前尝试读档会报出 relation does not exist, 属于正常现象
if (m.includes('timeout') || m.includes('relation')) {
world.say(m)
}
else {
world.say(msg || e.stack)//如果sql执行出错, 广播错误消息, 用来排查错误原因
console.log(fn)
}
}
await sleep(1000)
}
}
world.onPlayerJoin(({ entity }) => { //玩家进⼊游戏时
entity.player.onPress(async ({ button }) => { //每当有按钮被按下
if (button == Box3ButtonType.ACTION1) { //如果按钮是右键
const selection = await entity.player.dialog({
type: Box3DialogType.SELECT, //对话框类型为选择框
content: `${entity.player.name}\n欢迎回来`,
title: `控制⾯板`,
options: ['签到', '关闭'],
})
if (selection) { //确保对话框不是点击x关闭
if (selection.value === '签到') { //被点击的是保存按钮
var day2 = new Date();
day2.setTime(day2.getTime());
var today = day2.getFullYear() + "-" + (day2.getMonth() + 1) + "-" + day2.getDate();
const now = Date.now(); // 获取真实世界的时间戳 timestamp
const playerData = await getPlayerData_(entity.player.name); // 获取上次登陆记录
// 如果数据不存在,说明时第一次进入游戏
if (playerData == null) {
entity.player.score += 10
insertPlayer__(entity.player.name, today); // 插入玩家数据
entity.player.signtime = today
pollLV()
savePlayer(entity)
entity.player.dialog({
type: Box3DialogType.TEXT,
title: `系统`,
content: `签到成功\n获得10得分`,
options: ['确定'], // 将提供玩家选择的选项放入数组里。
});
} else if (entity.player.signtime != today) {
entity.player.score += 10
updatePlayerJoin_(entity.player.name, today); // 更新玩家进入游戏时间
entity.player.signtime = today
pollLV()
savePlayer(entity)
entity.player.dialog({
type: Box3DialogType.TEXT,
title: `系统`,
content: `签到成功\n获得10得分`,
options: ['确定'], // 将提供玩家选择的选项放入数组里。
});
} else {
entity.player.dialog({
type: Box3DialogType.TEXT,
title: `系统`,
content: `你今天签到了哦`,
options: ['确定'], // 将提供玩家选择的选项放入数组里。
});
}
}
}
}
})
})
最后告诉各位一个让大家绝望的消息:以上SQL代码仅pg数据库可使用
/**
简介
为什么要用PostgreSQL
使用SQLite数据库时, 有时因为人太多, 同一个游戏自动开了2服3服,多个服务器对同一个db文件写入引发了disk image malformed的问题, 造成了玩家群
体存储时的3种情形:
· 能够正常读档存档
· 只能读档无法存档
· 无法读档无法存档
虽然目前来说, 只有非常受欢迎的地图才会引发这个问题, 但越来越多玩家抱怨自己的游戏存档数据莫名丢失, 技术人员意识到SQLite的这个缺陷后, 决定
使用设计上更可靠的PostgreSQL数据库 (简称pg) 替代它.
PostgreSQL与SQLite在我们使用时的差别
pg和SQLite的语法大致相近, 但还是有些差别:
1. pg的字段名默认会强制转化成小写, 比如userKey会被当成userkey, 用到大写字母的名称要用"“包住才行, 例如"userKey”. 建议所有字段名/表名,
无论大小写都用""包住
2. 有时地图启动后, pg还未启动, 需要轮询等待pg到位
3. pg有时因为各种原因短暂下线, sql会执行不成功(比如query timeout), 需要轮询执行sql语句确保语句在数据库到位后继续执行
4. pg的INT整数字段有严格的位数限制, 超过上限将报错, 像1e+53这样的数值是存不进去的, 存进去之前先要把数值限制到有效数值范围(2147483喵7以下)
5. pg的INT整数字段还有另一个限制, 就是不能输入带有小数点的数字, 比如3.14这样的数字存进去会报错, 需要用Math.floor()把数值转成整数3再存入
6. pg里的字符串只能用’'包住, 不能用""包住, ""在pg只用于支持大写名称
7. 如果用到BIGINT类型, 它返回的是字符串而非数字, 在读取时需要用parseInt()转换回js里的整数
更多关于pg的细节教程:
就不告诉你链接
*/