用户:
MR_Wolf查看:309 回复:7 评论:40 创建时间:2023-03-27T20:41:46
总所周知SQL是每个出色地图不可或缺的代码
有的人还在困惑如何编写SQL
有的人甚至还在看api的代码但是老玩家或代码师都知道api这个东西不可信或者不是最优解,好久没更新什么有用内容了。
今天不继续bibi废话了 给大家介绍一些教程,禁止抄袭 : (
注:可能有点抽象但是没问题 详细讲解可以找作者 或 周围厉害的代码师
代码一:
适合萌新及新入门的代码师 这也是最优解
world.onPlayerJoin(async ({ entity: e }) => {
e.id = e.key()//设置
e.coin = 50
e.item = ['小菜']
e.data = {
exp: 50
}//以上为做地图可能会用到的基础信息
const temp = tempData[e.key()]//设置
if (temp) {
Object.assign(e, temp)//查找
}
})
const tempData = {}
world.onPlayerLeave(({ entity: e }) => {
const data = tempData[e.key()] || {}//设置
data.data =e.data
data.coin = e.coin
data.item = e.item//设置存档
tempData[e.key()] = data//存档
})
Box3Entity.prototype.key = function () {//萌新可以认为是 function key()
return this.player.userKey
}
注意:作者只能保证此存档玩家离开地图进入地图可以存档 其余需自己设置
代码二:
适合一般玩家
看api或者某一个自称是大佬的一个。。
(小插曲:吐槽一个事情,有个人叫作者帮忙搞一下地图,我进去后本来想复制走去别的地图帮他修,毕竟他地图有建筑,但代码不多,想着一会修完就帮他粘贴回来,然后他就开始质疑我,当我看到他说要修的东西在控制台显示的时候,然后直接说我不会,然后直接把我踢了,然后最后我找他理论,他说一个是大佬的人也不会修说我会?怼了我几句然后就把我删掉了,就是官方能管一管这些 自己为是的年度嘛???)
代码三:
适合一些把api学完的(坑)颠覆一下你的认知 当然这估计和官当代码比较接近了
const 创建 = {
async 表格(tbName, dict) {
const cmd = [`CREATE TABLE IF NOT EXISTS ${tbName} (${Object.entries(dict).map(([k, v]) => `${k} ${v}`).join(',')});`]
try {
return await db.sql(cmd)
} catch (e) {
world.say(e.stack)
}
},
async poll() {
while (true) {
try {
await db.sql`select 1;`
break
} catch (e) {
world.say('pg数据库启动中...')
}
await sleep(1000)
}
}
}
class 游戏开始 {
constructor() {
this.init()
}
async init() {
await 创建.poll()
await 创建.表格('player', {
userkey: "varchar(16) PRIMARY KEY not null",
boxid: "varchar(15) default ''",
item: "text default ''",
})
}
}
new 游戏开始()
function patch(玩家, 名称) {
const srcProto = 名称.prototype
for (const meth of Reflect.ownKeys(srcProto).slice(1)) {
玩家[meth] = srcProto[meth]
}
}
world.onPlayerJoin(async ({ entity: e }) => {
patch(e, 玩家的数据)
await e.初始化数据()
})
world.onPlayerLeave(({ entity: e }) => {
e.保存玩家('item', 'coin')
})
class 玩家的数据 extends Box3Entity {
async 初始化数据() {
await this.加载判断(['item', 'coin'])
this.enableDamage = true
}
玩家第一次数据() {
this.data = {
userkey: this.player.userKey,
boxid: this.player.boxId,
coin: 50,
item: ['小菜'],
}
}
async 加载(list) {
const userKey = this.player.userKey
while (true) {
try {
const data = (await (db.sql`SELECT * FROM player WHERE userkey=${userKey}`))[0]
if (data) {
for (const k of list) {
data[k] = JSON.parse(data[k])
}
this.data = data
return true
}
return false
} catch (e) {
world.say(e.stack)
}
await sleep(2000)
}
}
async 保存玩家(...keyList) {
const userKey = this.player.userKey
if (!userKey) this.player.directMessage('请先登录')
const data = this.data
const valList = keyList.map(e => {
const v = data[e]
if (v.constructor === Array || v.constructor === Object) {
return JSON.stringify(v)
}
else if (v.constructor === Number) {
return v | 0
}
return v
})
let head = keyList.shift()
let tail = keyList.map((e, i) => `,${e}=`)
const cmd = [`UPDATE player SET ${head}=`, ...tail, ` WHERE userkey=`, '']
while (true) {
try {
return await db.sql(cmd, ...valList, this.player.userKey)
} catch (e) {
world.say(e.stack + '\n@' + cmd + '\n#' + valList)
}
await sleep(300)
}
}
async insert(tbName, dict, key = 'userkey') {
const keyList = Object.keys(dict)
const valList = Object.values(dict).map((v, i) => {
if (v.constructor === Array || v.constructor === Object) {
return JSON.stringify(v)
}
return v
})
const cmd = [`INSERT INTO ${tbName} (${keyList})VALUES(`, ...(','.repeat(keyList.length - 1)), `) ON CONFLICT (${key}) DO NOTHING;`]
while (true) {
try {
return await db.sql(cmd, ...valList)
} catch (e) {
world.say(e.stack)
}
await sleep(300)
}
}
}
Box3Entity.prototype.加载判断 = async function (parseList) {
if (await this.加载(parseList)) {
this.player.directMessage('数据加载ing')
this.data.boxid = this.player.boxId
} else {
this.player.directMessage('数据创建ing')
this.玩家第一次数据()
if (!this.player.userKey) {
await this.insert('player', this.data)
}
}
}
若有什么不懂也可以问评论,作者会回复
当然请注意这是模板,不是最优解
如果要设置单个的玩家参数建议去看看代码一
看到这里了评个论或者转发一下吧
下个星期更新 新教程(qwq)
𝙲ℴ𝗌𝔦𝒹ₑ𝑟类型注释不是ts的吗(
Object:type
entity: e
)
这是什么()
点赞0
评论
这边建议你去学一下:) 就是比如 ... .onPlayerJoin(({entity:e})) 就是把entity改成e的意思 后面调用可以直接写e.coin 不用屑entity.coin
作者很生气aaaaaaaaaaa

作者疯掉了呢
点赞0
评论
class除非你有特殊object用途时才使用()一般建议function
《cmd》()
作者喜欢写普通人看不懂 除非讲解不能白嫖 的代码:)
🌿
作者 狠 喜欢白嫖怪的呢
SCS_user_LoeheodVOQ好好把api文档学完吧,这里面好多错误。
首先你要分清pg和sqlite,一般默认是sqlite数据库,不需要写poll函数,自己没有分清就来教别人
还有名称千万别用中文,要不然报错你都不知道是哪里,还有一段兼容性问题
entity不要有player的属性,要不然容易出错,这里面一大堆玩家属性权定义到实体上去了
还有所谓的萌新代码设计了一堆object和高级用法,看了教程还不如api,你都没有解释sql是干啥用的
点赞0
评论
ON CONFLIT什么也都是pg的代码,sqlite里面写就是多此一举
还有第一段代码根本没有用sql,地图关闭后数据就没了,算不上是存档系统
第三段代码我看着就难受,和官方代码差得多了,可读性极差
db.sql对于一般的代码直接用模板字符串就行了,不需要用模板+参数
我写这个的时候你可能不知道作者要干什么做什么地图:)
sql很简单,对我来说直接随便一个for()就刑了 关键是我就想知道为什么只是一个有一点人气的人 随便发一个教程 他就能变成精品[??????//为什么]
第一个是可以用的:) 这边建议来 https://box3.codemao.cn/e/20d0164cc015f604e5bf 我来给你亲测:)
而且api我看了一年了 一部分看明白了 还去看了一看比如菜鸟网站的代码 api雀氏是好久没更新了:)
等我周末 整
有一点常识的应该知道,地图会在三分钟没有人或夜里强制关闭,变量会强制删了
看明白了你连sqlite和pg都分不清???
就是你自己教程不好
强制重启确实但是应该是10分钟ba 而且你等我亿下
你等我亿下
不管是几分钟反正地图又不是一直运行的
敢问大哥岛id是什么
不过 只要不在创作端玩或更新发布应该是没问题的第一个[]
你可以试试,没用的
在主页
aaaaa 我不管大佬把你的岛名告诉我
我看看
好多独立的暴风雀 抱歉! 没有找到 QXN独立的暴风雀 的结果
ok呀找到了大佬喵问题现在做什么地图比较好aqwq