饥荒联机版

饥荒联机版

Insight (Show Me+)
 此主题已被置顶,因此可能具有重要性
penguin0616  [开发者] 2021 年 3 月 27 日 下午 12:11
Adding modded information
So, you've modded something and you want Insight to show information for it. Well, here's what you need to know.

Adding information for a component
The information Insight displays is largely based off of components. It iterates over each entity's components, checks if there's a valid descriptor for it, and runs the descriptor if it exists.
Here's one example of adding a descriptor:
-- modmain.lua local _G = GLOBAL local function AddDescriptors() if not _G.rawget(_G, "Insight") then return end _G.Insight.descriptors.my_component_name = { Describe = function(self, context) local description if context.player.name:find("a") then description = "You have an 'a' in your name!" else description = "You do <color=#ff0000>not</color> have an 'a' in your name.." end return { priority = 0, description = description } end } end AddSimPostInit(AddDescriptors) -- _G.Insight.descriptors may not exist yet, but it will exist at AddSimPostInit.

Note: Descriptor names are unique, and only one can exist for a component. So if there was another descriptor for "my_component_name", this would overwrite it.

Insight calls the Describe function with the parameters self and context.
self is a reference to the component, while context is background information about the player.

A rough example of context's structure is:
context = { player = player_entity, config = { -- configuration from insight ["display_upgradeable"] = true, ... }, external_config = { -- external mod related config ... }, usingIcons = true/false, -- whether the user is using icon formatting lstr = {...}, -- see scripts/language.lua is_server_owner = true/false, etc = {...} }

Descriptors can return nil, or a table. If returning a table, the table should look like in the example.
Priority is used for determing whether information shows up at the top or the bottom of an entity's overall information. Higher priority = higher spot.
Description can be nil or a string. It uses Insight's RichText system.

Adding information for a specific prefab
This follows essentially the same logic as adding information for a component, but with minor changes.
-- modmain.lua local _G = GLOBAL local function AddPrefabDescriptors() if not _G.rawget(_G, "Insight") then return end _G.Insight.prefab_descriptors.my_prefab = { Describe = function(inst, context) local description if context.player.name:find("a") then description = "You have an 'a' in your name!" else description = "You do <color=#ff0000>not</color> have an 'a' in your name.." end return { priority = 0, description = description } end } end AddSimPostInit(AddPrefabDescriptors)

Insight's RichText
Insight's RichText system lets you stylise your text to a small degree. The game's text rendering system is lacking, so we have to make do.
All descriptors' descriptions are run through this system.

It works on a tag based system, similar to XML or HTML.
RichText currently supports 4 stylings: coloring, icon insertion, superscript, subscript.

Coloring
local colored_text = "I like the colors <color=#0000cc>blue</color> and <color=#00cc00>green</color>. Hey, a <color=MOB_SPAWN>bearger</color>!"
The spacing is extremely important in tags, and they must obey the format outlined in the example.
Color can equal a hexadecimal color code, or they can be a specific color stored in _G.Insight.COLORS.
I sometimes store frequently used colors, such as MOB_SPAWN (which is #ee6666) in the COLORS table so I don't have to change multiple strings.

Icon Insertion
Probably the trickiest to work with out of all of the features. The gist of it is that an icon must exist in the icon_list table for it to work.
That table can be found in scripts/assets.lua
local text_with_icons = "You have a big <icon=health> sir, but your <icon=sanity> is weak."
Where <icon=health> is the health meter icon, and <icon=sanity> is the sanity meter icon.

Superscript, subscript
local super_and_sub = "2<sup>10</sup> is 1024. log<sub>b</sub>x = y."

That's pretty much it. There's a ton of examples in scripts/descriptors. So if there's a specific information style you want to use, just look at the responsible descriptor.
Let me know if you have any questions.
最后由 penguin0616 编辑于; 2022 年 7 月 21 日 下午 1:19
< >
正在显示第 1 - 12 条,共 12 条留言
Serp 2022 年 7 月 21 日 上午 2:35 
I think one should add within the local function a check if Insight mod is enabled by checking if the global variable exist:
if _G.rawget(_G,"Insight") and _G.Insight~=nil then
Otherwise it will most likely crash if the mod runs withoug Insight enabled?!
penguin0616  [开发者] 2022 年 7 月 21 日 下午 1:19 
引用自 Serp
I think one should add within the local function a check if Insight mod is enabled by checking if the global variable exist:
if _G.rawget(_G,"Insight") and _G.Insight~=nil then
Otherwise it will most likely crash if the mod runs withoug Insight enabled?!
Thanks, code was adjusted.
Serp 2022 年 7 月 31 日 下午 6:26 
How to add information to things that already have a descriptor without overwriting it? (I want just append to the description string)
penguin0616  [开发者] 2022 年 7 月 31 日 下午 7:15 
引用自 Serp
How to add information to things that already have a descriptor without overwriting it? (I want just append to the description string)

I was writing an example in response to your question, and realized that there's no good way to do it at the moment since descriptors' Describe can return a bunch of nils or tables. I'll have to think about what can be done.

That being said, here's the example. This sort of thing is probably the best option at the moment.
local Insight = _G.Insight if type(Insight.descriptors.burnable) == "table" and Insight.descriptors.burnable.Describe then local oldDescribe = Insight.descriptors.burnable.Describe Insight.descriptors.burnable.Describe = function(self, context, ...) local packed = Insight.env.pack(oldDescribe(self, context, ...)) for i,v in ipairs(packed) do if v and v.name == "burnable" and v.description then -- apply description changing logic here v.description = "Stuff: " .. v.description break end end return Insight.env.vararg(packed) end end
最后由 penguin0616 编辑于; 2022 年 7 月 31 日 下午 7:15
Serp 2022 年 7 月 31 日 下午 8:45 
thanks, so my final code to append sth on the edible component is working like this:
(edited after your first response)

local _G = GLOBAL local function AddDescriptors() if not _G.rawget(_G, "Insight") then return end local oldDescribe = nil if _G.Insight.descriptors.edible==false then return end -- if it is false something went wrong in Insight so we can not change it, must be fixed within Insight if type(_G.Insight.descriptors.edible) == "table" then if _G.Insight.descriptors.edible.Describe then oldDescribe = _G.Insight.descriptors.edible.Describe end else _G.Insight.descriptors.edible = {} end _G.Insight.descriptors.edible.Describe = function(self, context,...) local my_description = "my edible description" if oldDescribe~=nil then -- if anyone already added a description, do not overwrite it, but add stuff to it local packed = _G.Insight.env.pack(oldDescribe(self, context, ...)) local old_description = "" if my_description~=nil then for i,v in ipairs(packed) do if v and v.name == "edible" then old_description = v.description or "" v.description = old_description.."\n"..my_description -- append description break end end end return _G.Insight.env.vararg(packed) else return { priority = 10, description = my_description } end end end AddSimPostInit(AddDescriptors)

small question:
The code checks for "v.name", while your example code in the first post does not return a "name". Is this added automatically by your mod? Or should we always add a name to the returned values?
And maybe also add "alt_description" to your example.
最后由 Serp 编辑于; 2022 年 7 月 31 日 下午 10:26
penguin0616  [开发者] 2022 年 7 月 31 日 下午 10:12 
引用自 Serp
small question:
The code checks for "v.name", while your example code in the first post does not return a "name". Is this added automatically by your mod? Or should we always add a name to the returned values?
And maybe also add "alt_description" to your example.

It's another one of those issues in the example where modding the describe functions is difficult. If a descriptor returns a table without a name field, it gets automatically added in later. I specify the name ahead of time if the Describe returns multiple tables, since it's a requirement in that case. When there isn't a name, you just hope it's the first return.

In your case, since you're modifying edible, it already has the name so you should be okay.

I would change this:
if type(_G.Insight.descriptors.edible) == "table" and _G.Insight.descriptors.edible.Describe then oldDescribe = _G.Insight.descriptors.edible.Describe else _G.Insight.descriptors.edible = {} end
to remove the else & table assignment,
If it's not a table, that means it's probably false, which means it likely hit an error during loading. You'd just be suppressing the error at that point, which is not recommended. Better to see why it's erroring.
Serp 2022 年 7 月 31 日 下午 10:27 
引用自 penguin0616
I would change this:
to remove the else & table assignment,
If it's not a table, that means it's probably false, which means it likely hit an error during loading. You'd just be suppressing the error at that point, which is not recommended. Better to see why it's erroring.
hm... simply removing it does not work, because it also may be "nil" if no other mod defined it yet. (the code should also work to be compatible to other mods that are adding descriptions, also to things Insight does not add one).

I edited the code above to check for "false" and only set edible a new table if is no table yet. Unless you need no other "non-table" values, this should be fine now I guess.
最后由 Serp 编辑于; 2022 年 7 月 31 日 下午 10:28
penguin0616  [开发者] 2022 年 7 月 31 日 下午 10:30 
引用自 Serp
hm... simply removing it does not work, because it also may be "nil" if no other mod defined it yet. (the code should also work to be compatible to other mods that are adding descriptions, also to things Insight does not add one).

I edited the code above to check for "false" and only set edible a new table if is no table yet. Unless you need no other "non-table" values, this should be fine now I guess.


descriptors is a metatable. When you index it to check for a descriptor, it first tries to load it if it hasn't been loaded yet. The descriptor should never be nil. It will always be a table or false.
最后由 penguin0616 编辑于; 2022 年 7 月 31 日 下午 10:31
Wonderlarr 2022 年 9 月 28 日 上午 4:37 
How can I remove a component descriptor for a specific prefab? I have a unique case where I'm using the Fueled component in a sortof weird way within my mod which insight is detecting as Fuel Efficiency being 1.6666666667%. I'd like to hide this, since although it's accurate, it's already cluttered enough https://i.imgur.com/vIMoo1i.png
penguin0616  [开发者] 2022 年 10 月 1 日 下午 8:33 
@Skylarr I'm debating adding a "AddDescriptorPostDescribe" function. I feel that would likely work. Thoughts?
penguin0616  [开发者] 2023 年 1 月 24 日 下午 6:07 
I've added AddDescriptorPostDescribe(modname, descriptor, callback) for modders to use (inside of the Insight environment).
The callback is called with the component and table of data returned from the descriptor's Describe.
penguin0616  [开发者] 2024 年 8 月 1 日 下午 3:32 
@伺夜 I don't understand the request.
< >
正在显示第 1 - 12 条,共 12 条留言
每页显示数: 1530 50