饥荒联机版Mod开发——class, prefab, component,debug(四)

  • Class的使用方法
  • Prefab
  • component
    • Entity Component
    • Normal Component
  • debug
    • 控制台
    • 日志
    • 可视化调试
  • Class的定义
  • 传送门

Class的使用方法

Lua中原本是没有类的,不过饥荒自己写了个(源代码在class.lua)。

function Class(base, _ctor, props) ... end   --return table
  • base:基类,通常是 require(“某类”)
  • _ctor:构造函数,函数参数(self, …),调用时自动传个{}作为self,我们只传后面的参数
  • props:属性列表,例如{ key = fn },函数参数(self, newvalue, oldvalue)
    注:当base为function,而_ctor为nil时会交换base和_ctor
    这里的 self 可以理解为其他编程语言中的 this 。调用Class这个函数后,会注册了一个类,并返回该类(一个table)。定义一个类,通常的写法是
--例如在 xxx.lua 中
--除了self以外的参数,其他参数需要我们自己传
local XXX = Class(function(self, str) self.str = str  --成员变量print("构造函数")
end)--相当于 XXX.fn = function(self) print(self.str) end
function XXX:fn()print("成员函数")print(self.str)
endreturn XXX

当我们需要生成一个对象和使用成员函数时,

--在script根目录下的.lua文件一般会在main.lua中require(),我们不需要自己require,如Vector3
local XXX = require("xxx")   --加载xxx.lua,并里面的返回return值
local obj = XXX("Hello World")   --调用构造函数生成对象
--相当于 obj.fn(obj)
obj:fn()    --调用成员函数
obj.str = "你好世界"     --修改成员变量

当需要使用属性时,通常这么写

--例如在 xxx.lua 中
--[[  self.str = newstr 的调用过程如下local oldstr = self.strrawset(self, "str", newstr)   --不触发属性的赋值,调用后,self.str被赋值为newstronstr(self, newstr, oldstr)
--]]
local function onstr(self, newstr, oldstr)--一开始的oldstr为nil,所以构造函数时就会触发属性-- str..str,str..num,num..str,字符串连接if oldstr~=nil then print("oldstr: "..oldstr) endprint("newstr: "..newstr)
end
--除了self以外的参数,其他参数需要我们自己传
local XXX = Class(function(self, str) self.str = str  --成员变量print("构造函数")
end,
nil,
{--这个表的key对应构建函数里的self.keystr = onstr
})--相当于 XXX.fn = function(self) print(self.str) end
function XXX:fn()print(self.str)
endreturn XXX

当我们需要生成一个对象和使用成员函数时,

--在script根目录下的.lua文件一般会在main.lua中require(),我们不需要自己require,如Vector3
local XXX = require("xxx")   --加载xxx.lua,并里面的返回return值
local obj = XXX("Hello World")   --调用构造函数生成对象
--相当于 obj.fn(obj)
obj:fn()    --调用成员函数
obj.str = "你好世界"     --修改成员变量,会自动调用onstr函数

Prefab

预设物,可以简单理解为模版(模具),方便我们创建相同的游戏实体(Entity)。在饥荒里面预设物(Prefab)由名字(name)、资源(assets)、构造函数(ctor/fn)、依赖预设物(depends)组成。下面是其定义(源代码 prefabs.lua)

--注册名字为name的预设物
--前两个参数是必须的,后面的默认分别是 {}, {}, false
Prefab = Class( function(self, name, fn, assets, depends, force_path_search) ... end)
  • name:独一无二的预设物名,mod的预设物最好加个前缀,避免和官方预设物冲突
  • fn:构造函数,无参数,返回 Entity(即我们常见的 inst = CreateEntity() … return inst)
  • assets:该预设物需要的资源,动画,贴图,音效等,如 { Asset(…), Asset(…) }
  • depends:依赖的预设物,通常生物会依赖于其掉落物,如 猪人的{ “meat”, “pigskin” }
  • force_path_search:resolvefilepath等函数会用来强制搜索路径,我们一般用不上

当我们使用 Prefab(…) 时,仅仅是创建好了对应名字的模版(模具),在游戏里面看不见摸不着,只要通过这个模版(模具)创建出游戏实体(Entity)时,我们才能看见这个物体(Entity)。

生成空实体,常见于各prefab文件的fn中

function CreateEntity() ... end   --return table

生成预设物实体,这个代码里用得比较多的,一般mod物品传个name就可以了。
(不用想着生成没有对应皮肤的物品,会判断玩家creator的Id的来看看你有没有皮肤)

--对应Prefab时传入的name,后面三参数可省
--返回Entity,也就是常见的 inst
function SpawnPrefab(name, skin, skin_id, creator) ... end

或者控制台命令

--consolecommmands.lua
--num可默认为1
c_give(name, num)   --给予玩家物体,需包含 inventoryitem 组件
c_spwan(name, num)  --在鼠标出生成实体

而注册预设物说需要的资源是通过下面的API(assets列表),一种type对应一种文件后缀

--也在prefabs.lua, param可省
Asset = Class( function(self, type, file, param) ... end)
--常见的type及其后缀
local assets = {Asset("IMAGE", "images/inventoryimages/xxx.tex"),Asset("ATLAS", "images/inventoryimages/xxx.xml"),Asset("SOUND", "sound/rabbit.fsb"),Asset("ANIM", "anim/beard_monster.zip"),Asset("SCRIPT", "scripts/prefabs/player_common.lua"), --官方代码
}

component

写mod大多数时候是和组件打交道的。而组件又可以分为两种

  • Entity Component:C层,看不见源码,能参考的只有官方代码中的调用
  • Normal Component:Lua层,源码在scripts/components,Class

Entity Component

实体组件包括下面几个(个人总结)

  • Transform:变换组件,控制位置、方向、缩放等等
  • AnimState:动画组件,控制动画的播放
  • Phiysiscs:物理组件,控制物理行为,比如速度,碰撞类型等
  • Light:光照组件,添加该组件可使得实体成为一个光源
  • Network:网络组件,服务器和客户端的桥梁
  • MiniMapEntity:地图实体组件,为实体在地图上创建图标。
  • MiniMap:c side renderer,一般用在生成地图
  • SoundEmitter:声音组件,控制声音播放等
  • Follower:让贴图跟随目标

对应的API,可以看第一期提供资源里的
笔记/笔记:物品制作常见组件.lua

不过推荐大家去下载我最新的笔记
https://github.com/SunRiver-Kun/DST_Notes
一般使用方法如下(以Transform为例)

--添加方法: inst.entity:AddXXX()
inst.entity:AddTransform()
--使用方法:  inst.XXX:YYY()
inst.Transform:SetPosition(0, 0, 0)

Normal Component

这部分组件在scripts/components文件夹下。

我们拿个简单的组件介绍下具体写法(components/health.lua),看之前首先要了解Class

local function oncurrenthealth(self, currenthealth)--用对应replica组件通知客户端更新血量       netvar
endlocal Health = Class(function(self, inst)self.inst = instself.maxhealth = 100self.minhealth = 0self.currenthealth = self.maxhealth
end,
nil,
{currenthealth = oncurrenthealth,
})--[[amount:变化的数值,正值回血,负值扣血,大部分时候只用这个参数即可overtime:是否总是,仅用于传递消息,用于客户端显示箭头等cause:原因,仅用于传递消息ignore_invincible:是否忽视无敌afflicter:攻击者(玩家),PVP伤害吸收ignore_absorb:是否忽略吸收伤害(是否是真伤)
--]]
function Health:DoDelta(amount, overtime, cause, ignore_invincible, afflicter, ignore_absorb)
end

使用方法

--添加组件,如果同名后缀的 _repica 的通信组件也会一起加上
inst:AddComponent("health")   --对应scripts/components/health.lua
--效果和这个差不多 inst.components["health"] = require("components/health")(inst)
inst.components.health:DoDelta(10)  --回血
--inst:RemoveComponent("health")  移除组件

debug

饥荒的调试
一个Entity大概有什么,到后面可视化调试部分可以自己去游戏里看看

--local inst = CreateEntity()
local inst = {--key = valuename = "实体名",GUID = number,prefab = "预设物名",components = {  --对应scripts/componets文件夹下的文件夹名component_name = {},...},replica = {},  --对应scripts/componets文件夹下的_repica组件--对应的Entity组件名等Transform = {},children = {--这里的key不是字符串,而是 entityentity1 = true},HUD = {},    --基本UI界面,就是血条等UI所在的Screenevent_listening = {},  --监听中的事件event_listeners = {},  --被监听的事件sg = {},   --state graph,状态机,切换动画用inlimbo = boolean,    --是否在物品栏内--下面是玩家特有的userid = string,    --KU_XXXisplayer = true,   --可以用 inst.isplayer 来判断是否是玩家
}

控制台

如果是在不开洞穴下直接使用,开洞穴,建议把命令模式按Ctrl调为远程(remote)
按~调出控制台,输入对应代码,回车。
Ctrl + L:显示log日志
Back

--[[
为方便书写,指出
prefab、tag、name、str 是string
num 是number
inst、entity 是 Entity
mouseEntity 是当前鼠标下的Entity
ThePlayer 是当前玩家
特殊说明如 : string|number ,表示变量是string或numberfunction fn(...) ... end --参数自己决定, 具体代码省略
function fn2(num = 1) ... end --num可以忽略,并默认为1
--]]print(...) -- 最原始的调试方法,不开洞穴时,可以直接打印到屏幕上,开洞穴就需要去日志找
--consolecommands.lua
c_reset()   --回挡,常用于修改代码后,重新快速加载
c_save()    --存档
c_select(entity=mouseEntity)   --选定并返回entity,不开洞穴获取服务器实体,开则是客户端实体
c_sel() --返回上一个选定的entity
c_spawn(prefab, num=1) --生成预设物实体
c_give(prefab, num=1)  --给予预设物实体
c_freecrafting()    --开启/关闭物品全制作,第一次开启,第二次关闭,第三次开启,……
c_despwan(player=ThePlayer)    --重新选人
c_godmode(player=ThePlayer)    --开启/关闭上帝模式,无敌,角色死亡则是复活
c_supergodmode(player=ThePlayer)   --开启/关闭上帝模式,回满三维,角色死亡则是复活
c_remove(entity=mouseEntity)   --移除实体
c_gonext(name)  --移动到目标位置,如 c_gonext("pigking")
c_remote(str)   --远程执行命令,主要是在代码里面用的

日志

在不开洞穴的情况下日志在 我的文档 -> Klei -> DoNotStarveTogether(Rail) -> client_log.txt,如果游戏直接蹦了或需要看print的全部信息,就需要来看这个日志了。如果是错误,直接搜 error 即可,打印的就需要加个后缀来方便查找了(如 ++++++++++++++++)

如果开了洞穴,上面这个就是客户端日志,对应服务器日志在
*我的文档 -> Klei -> DoNotStarveTogether(Rail) -> 一串数字 -> Cluster_X - > Master/Caves -> server_log.txt


这里Cluster_X指世界列表中的第几个世界,不过一般不是很准确,所以会看 cluster.ini

可视化调试

首先需要订阅相关mod
steam

wg

如果不开洞穴,只用左边那个就足够了。如果开洞穴就需要再多开个右边的mod。
用法同控制台代码,按~打开控制台,输入对应代码,回车就行。
介绍以下主要的API,s_开头的是左边的mod,sr_开头的是右边的mod

--SR_DebugHelp
s_help()    --打印帮助s_show(data:any) --显示数据,如 s_show(ThePlayer)  或  s_show(s_get())
s_data()  --返回当前的数据s_get()  --返回鼠标下实体
s_inst() --返回上一个实体或鼠标下实体s_getui()  --返回鼠标下UI
s_ui()  --返回上一个或鼠标下UI--SR_DebugHelperExtension
sr_help()   --打印帮助
printf(...)     --打印服务器数据到客户端
sr_xxx()    --和 s_xxx 效果相似,远程处理服务器数据,本地处理客户端数据

s_show的效果,如下图。点击元素可以修改(某些不能改的硬改会蹦)。

可通过mod设置改颜色和进游戏自动上帝模式和物品全制作。
对了,输入 ( 时,不能马上输入 ),否则代码提示会消失

Class的定义

这部分属于进阶知识,多学总没有坏处。
Class的定义在class.lua,想要看懂它,首先要学习Lua的元表
https://www.runoob.com/lua/lua-metatables.html

--base:基类,通常是 require("某类")
--_ctor:构造函数,函数参数(self, ...),调用时自动传个{}作为self,我们只传后面的参数
--props:属性列表,例如{ key = fn },local function fn(self, newvalue, oldvalue) ... end
function Class(base, _ctor, props) local c = {}    --一个新的类--当base是函数,而_ctor为nil时,交换base和_ctor--如果base不为nil,拷贝base的数据到c--设置 c.__index和c.__newindexlocal mt = {}   --c的元表,让我们可以通过 c(...) 来调用其c._ctor(...)mt.__call = function(class_tbl, ...) local obj = {}setmetatable(obj, c)  --当obj中没对应key时来c.__index找,设置值时用c.__newindexc._ctor(obj, ...) --我们只需要传递self后的参数return objendc._ctor = ctorc.is_a = function(self, klass) ... end  --判断当前类是否是klass的子类的函数setmetatable(c, mt)  --设置c的元表为mt,让我们可以通过 c(...) 来调用其c._ctor(...)return c
end

传送门

→饥荒联机版Mod开发——modmain(五)
←饥荒联机版Mod开发——制作简单的物品(三)

饥荒联机版Mod开发——Class, Prefab, component,debug(四)相关推荐

  1. 饥荒联机版Mod开发——modmain(五)

    饥荒联机版Mod开发--modmain(五) 前言 modmain环境 常用方法 设置环境具体流程 mods.lua modutil.lua 传送门 前言 在modmain中我们可以通过 Prefab ...

  2. 饥荒联机版Mod开发——常用inst方法(八)

    饥荒联机版Mod开发--常用inst方法(八) 前言 生成实体 监听/推送事件 使用标签 增删组件 网络组件 定时/阶段任务 回调函数 父子实体 平台 删除 位置,角度 显示/隐藏 判断 大脑 状态图 ...

  3. 饥荒联机版Mod开发——制作可入锅,烹饪,凉干的食物(七)

    饥荒联机版Mod开发--制作可入锅,烹饪,凉干的食物(七) 可入锅 可烹饪 可凉干 传送门 可入锅 参考:cooking.lua 先来看一下官方代码 --names:{"prefab1&qu ...

  4. 饥荒联机版Mod开发——衣服(十一)

    饥荒联机版Mod开发--衣服(十一) 前言 总览与下载 modmain prefab 动画 前言 饥荒里面装备栏有三个地方,手,身体,头.上一期我们讲了戴头上的帽子,这期我们讲讲穿在身上的衣服.事实上 ...

  5. 饥荒联机版Mod开发——准备工具(一)

    饥荒联机版Mod开发--准备工具 前言 工具下载 工具功能和使用 动画 c_start:反解压动画 Sprite:制作动画 打包工具:把动画再打包回去 贴图 TEXTool:查找/反解压tex tex ...

  6. 饥荒联机版Mod开发——两种帽子(十)

    饥荒联机版Mod开发--两种帽子(十) 前言 总览与下载 动画 代码 modmain 露头类帽子 基本的预设物框架 穿戴 可交易 腐烂及可放冰箱 总的代码 不露头类帽子 差异 基本代码 耐久 其他功能 ...

  7. 饥荒联机版Mod开发——制作烹饪锅食物(六)

    饥荒联机版Mod开发--制作烹饪锅食物(六) 前言 准备工作 编写菜谱 制作预设物 添加菜谱 传送门 前言 核心组件及其流程如下: 材料 -> 烹饪锅(stewer) -> 食物(吃edi ...

  8. 饥荒联机版Mod开发——配置代码环境(二)

    饥荒联机版Mod开发--配置代码环境(二) 前言 下载VS Code和Lua插件 建立工作区 配置Lua插件 Git和GitHub(可选) 排除多余文件 删除scripts里多余文件 VS Code快 ...

  9. 饥荒联机版服务器mod模组在哪个文件夹,饥荒联机版MOD使用图文教程_饥荒联机版MOD怎么用_牛游戏网...

    饥荒联机版相信大家都玩得不亦乐乎,在饥荒中使用MOD也是一大乐趣,不少萌新可能还不知道饥荒联机版怎么使用MOD,饥荒联机版MOD要怎么安装使用呢,下面小编就为大家带来了饥荒联机版MOD使用图文教程,给 ...

最新文章

  1. 解决 Ubuntu 无法更新软件问题
  2. 【壹刊】Azure AD B2C(一)初识
  3. 安全密码存储–请勿做的事和Java示例
  4. 飞畅科技告诉你什么是集成串口服务器POE交换机?
  5. Go 语言——基本类型
  6. rost反剽窃检测系统_学术不端检测规则是什么?
  7. 人大金仓数据库 Windows安装教程 -kingbase8R6
  8. TwinCAT 3 基础——编程基础
  9. python百度地图api添加坐标点_python调用百度地图API实现经纬度换算、热力地图全流程指南...
  10. 未来人类笔记本 T5 67SH2 扩展内存条
  11. Apache druid的ingestion spec数据插入规范
  12. 关于Kaggle入门Titanic的一次简单尝试Part 2 -- Dive into ML
  13. Default changeset implementation allows only one operation
  14. 时光穿梭机特效如何制作?建议试试这个时光机穿梭工具
  15. 我的电脑里顽固图标删除解决
  16. 【点云配准】点云配准中常用的评价指标(豪斯多夫距离/Hausdorff Distance、倒角距离/Chamfer Distance和陆地移动距离/Earth Mover‘s Distan
  17. 计算机全能学什么,什么是全能学生本 全能学生本什么意思
  18. JAVA计算机毕业设计喜枫日料店自助点餐系统(附源码、数据库)
  19. string去掉末尾符号
  20. 纳米表征技术 2022.10.5

热门文章

  1. 筛选法与试除法 判断素数
  2. 送书 | 《趣学Python算法100例》
  3. 如何把eclipse的背景色改为豆沙色
  4. 学习yade日常错误2019.3.22
  5. webatm取款操作_大话JS面向对象之开篇万物皆对象------(ATM取款机引发的深思)...
  6. Hive表设置支持中文注释、中文表数据导入
  7. Visio生成eps文件的方法
  8. GHOST系统封装教程 系统封装工具 XP系统封装(三)
  9. 股票/转债数据获取工具
  10. 2017 TFC:第四届TFC VR AR高峰论坛精彩盘点