猫史档案馆


BOX3颠覆你的认知 神奇的SQL(第一期)

用户:MR_WolfMR_Wolf查看:40 回复: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)

 

 


回复

上一页1 页 / 共 1下一页
MR_WolfMR_Wolf

不知道啥bug好绿

点赞0


评论


MR_WolfMR_Wolf

为什么别人随手一发还不符合的论坛直接火

我这个。。。。

点赞0


评论


𝙲ℴ𝗌𝔦𝒹ₑ𝑟𝙲ℴ𝗌𝔦𝒹ₑ𝑟

类型注释不是ts的吗(

Object:type

entity: e

这是什么()

点赞0


评论


憨白不憨awa憨白不憨awa

ddd

点赞0


评论


𝙲ℴ𝗌𝔦𝒹ₑ𝑟𝙲ℴ𝗌𝔦𝒹ₑ𝑟

center_image仔细看看

点赞0


评论


MR_WolfMR_Wolf

center_image

作者疯掉了呢

点赞0


评论


SCS_user_LoeheodVOQSCS_user_LoeheodVOQ

好好把api文档学完吧,这里面好多错误。

首先你要分清pg和sqlite,一般默认是sqlite数据库,不需要写poll函数,自己没有分清就来教别人

还有名称千万别用中文,要不然报错你都不知道是哪里,还有一段兼容性问题

entity不要有player的属性,要不然容易出错,这里面一大堆玩家属性权定义到实体上去了

还有所谓的萌新代码设计了一堆object和高级用法,看了教程还不如api,你都没有解释sql是干啥用的

点赞0


评论