玩家系统示例
本示例展示如何使用 Sleet ORM 构建一个完整的 FiveM 玩家管理系统,包括注册、登录、数据管理和经验系统。
Schema 设计
lua
-- server/schema.lua
local sl = Sleet
local players = sl.table('players', {
id = sl.serial().primaryKey().comment('玩家ID'),
identifier = sl.varchar(64).notNull().unique().comment('Steam/Discord标识符'),
name = sl.varchar(255).notNull().comment('玩家名称'),
money = sl.int().default(5000).comment('现金'),
bank = sl.int().default(25000).comment('银行存款'),
level = sl.int().default(1).comment('等级'),
experience = sl.bigint().default(0).comment('经验值'),
playtime = sl.int().default(0).comment('游戏时长(分钟)'),
is_admin = sl.boolean().default(false).comment('管理员'),
is_banned = sl.boolean().default(false).comment('封禁状态'),
banned_until = sl.timestamp().comment('封禁到期时间'),
metadata = sl.json().comment('扩展数据'),
last_seen = sl.timestamp().defaultNow().comment('最后在线时间'),
created_at = sl.timestamp().defaultNow().comment('创建时间'),
updated_at = sl.timestamp().defaultNow().onUpdate(sl.sql('NOW()')).comment('更新时间')
})
-- 成就表
local achievements = sl.table('achievements', {
id = sl.serial().primaryKey(),
name = sl.varchar(100).notNull().unique().comment('成就名称'),
label = sl.varchar(255).notNull().comment('显示名称'),
description = sl.text().comment('成就描述'),
icon = sl.varchar(255).comment('图标'),
reward_money = sl.int().default(0).comment('奖励金钱'),
reward_exp = sl.int().default(0).comment('奖励经验'),
is_active = sl.boolean().default(true).comment('是否启用')
})
-- 玩家成就表
local player_achievements = sl.table('player_achievements', {
id = sl.serial().primaryKey(),
player_id = sl.int().notNull().references(players.id).comment('玩家ID'),
achievement_id = sl.int().notNull().references(achievements.id).comment('成就ID'),
earned_at = sl.timestamp().defaultNow().comment('获得时间')
})
return {
players = players,
achievements = achievements,
player_achievements = player_achievements
}核心功能实现
玩家管理类
lua
-- server/player.lua
local sl = Sleet
local s = require 'server.schema'
local db = sl.connect()
local PlayerManager = {}
-- 获取或创建玩家
function PlayerManager.GetOrCreate(identifier, name)
-- 先尝试获取现有玩家
local existing = db.select()
.from(s.players)
.where(sl.eq(s.players.identifier, identifier))
.limit(1)
.execute()[1]
if existing then
-- 更新最后登录时间和名称
db.update(s.players)
.set({
name = name,
last_seen = sl.sql('NOW()')
})
.where(sl.eq(s.players.id, existing.id))
.execute()
return existing
else
-- 创建新玩家
local newId = db.insert(s.players)
.values({
identifier = identifier,
name = name,
metadata = {
first_join = os.date('%Y-%m-%d %H:%M:%S')
}
})
.execute()
-- 返回新创建的玩家数据
return db.select()
.from(s.players)
.where(sl.eq(s.players.id, newId))
.limit(1)
.execute()[1]
end
end
-- 获取玩家信息
function PlayerManager.GetById(playerId)
return db.select()
.from(s.players)
.where(sl.eq(s.players.id, playerId))
.limit(1)
.execute()[1]
end
function PlayerManager.GetByIdentifier(identifier)
return db.select()
.from(s.players)
.where(sl.eq(s.players.identifier, identifier))
.limit(1)
.execute()[1]
end
-- 更新玩家金钱(安全方式)
function PlayerManager.AddMoney(playerId, amount, reason)
reason = reason or '未知原因'
local affected = db.update(s.players)
.set({
money = sl.sql('money + ?', { amount }),
updated_at = sl.sql('NOW()')
})
.where(sl.and_(
sl.eq(s.players.id, playerId),
sl.gte(sl.sql('money + ?', { amount }), 0) -- 防止负数
))
.execute()
if affected > 0 then
print(string.format('玩家 %d 金钱变化: %+d (原因: %s)', playerId, amount, reason))
return true
end
return false
end
-- 银行操作
function PlayerManager.AddBank(playerId, amount, reason)
reason = reason or '银行操作'
local affected = db.update(s.players)
.set({
bank = sl.sql('bank + ?', { amount }),
updated_at = sl.sql('NOW()')
})
.where(sl.and_(
sl.eq(s.players.id, playerId),
sl.gte(sl.sql('bank + ?', { amount }), 0)
))
.execute()
return affected > 0
end
return PlayerManager经验等级系统
lua
-- server/experience.lua
local sl = Sleet
local s = require 'server.schema'
local db = sl.connect()
local ExperienceManager = {}
-- 计算等级所需经验(每级需要的经验递增)
function ExperienceManager.GetRequiredExp(level)
return math.floor(100 * (level ^ 1.5))
end
-- 根据经验计算等级
function ExperienceManager.CalcLevel(experience)
local level = 1
while experience >= ExperienceManager.GetRequiredExp(level + 1) do
level = level + 1
end
return level
end
-- 给予经验
function ExperienceManager.GiveExperience(playerId, amount, reason)
reason = reason or '获得经验'
-- 获取当前玩家数据
local player = db.select({ s.players.level, s.players.experience })
.from(s.players)
.where(sl.eq(s.players.id, playerId))
.limit(1)
.execute()[1]
if not player then
return false, '玩家不存在'
end
local newExp = player.experience + amount
local newLevel = ExperienceManager.CalcLevel(newExp)
local oldLevel = player.level
-- 更新经验和等级
db.update(s.players)
.set({
experience = newExp,
level = newLevel,
updated_at = sl.sql('NOW()')
})
.where(sl.eq(s.players.id, playerId))
.execute()
-- 检查是否升级
if newLevel > oldLevel then
print(string.format('玩家 %d 升级: %d -> %d', playerId, oldLevel, newLevel))
-- 这里可以触发升级奖励
ExperienceManager.OnLevelUp(playerId, oldLevel, newLevel)
end
return true, newLevel
end
-- 升级回调
function ExperienceManager.OnLevelUp(playerId, oldLevel, newLevel)
-- 升级奖励金钱
local rewardMoney = (newLevel - oldLevel) * 1000
local PlayerManager = require 'server.player'
PlayerManager.AddMoney(playerId, rewardMoney, '升级奖励')
-- 这里可以触发其他升级效果
TriggerClientEvent('player:levelUp', playerId, {
oldLevel = oldLevel,
newLevel = newLevel,
rewardMoney = rewardMoney
})
end
return ExperienceManager更多内容请查看完整实现...
