[Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

[Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

Simple_Dialogs for Minetest entities

* version 0.31 *

By Kilarin

This mod allows you to add dialogs for npcs and other entities, controlled by an in game text file.

source: https://github.com/Kilarin/simple_dialogs/

ContentDB: https://content.minetest.net/packages/K ... e_dialogs/

Image

Simple Dialogs is NOT a stand alone entity mod, rather it is an add on that is designed to be (rather easily) integrated with other entity mods.

TenPlus1 has very generously already integrated simple_dialogs into his mobs_redo/mobs_npcs. So if you wish to try it out you can use his mod:
https://notabug.org/TenPlus1/mobs_redo https://notabug.org/TenPlus1/mobs_npc


Simple Dialogs allows you to create conversation trees (dialogs) for any entity. And those dialogs are created using only a simple in game text file. No API or LUA programming required.

Image

This means that any player who has ownership of an npc can create their own customized dialogs for that npc. A player building a shop can write a dialog for the npc shop keeper. A player who builds a huge castle can craft their own custom dialog for the guard at the gate to tell people about the castle. AND, since the control mechanisim is just text, the players have no direct lua access, avoiding some security risks.

Of course, dialogs can be used by the server owner/game designer as well. They can create individually customized dialogs for npcs in the same manner that any player can. BUT, they can also add a text file containing a dialog to the game folder, and have it automatically uploaded to specific kinds of entities whenever they are spawned.


====================
So, how does all of this work? Expand the spoiler for details!
Spoiler
The heart and key to simple dialogs is the dialog control text. Which, at it's simplest, looks something like this:

Code: Select all

===Start
Shiver me timbers, but you caught me by surprise matey!
What be ye doin here?  Arrrgh!  This be no fit place for land lubbers!
>name:What is your name
>arrg:Why do pirates always say Arrrgh?
>treasure:I'm looking for treasure.  Can you tell me where the treasure is?
>rude:What's got you so cranky?  Did a beaver chew on your wooden leg?
TOPICS

The dialog starts with a topic, a topic is any line that has an equal sign "=" in position one. Every dialog file must have at least one START topic. Topics are not case sensitive, and any characters besides letters, digits, dashes, and underscores are removed. Start, start, st art, and START will all be treated the same by simple dialogs. This also means all equal symbols will be removed. Every topic must start with one equal sign, I like three, I think it makes them stand out more, but it doesn't matter how many equal signs you have at the begining, as long as you have at least one, in position one. You can also add a "weight" to a topic line if you wish, we will talk more about that later.

Following the topic will be the dialog you want the character to say. This can be as long or as short as you wish. Just don't start any lines with "=", ":", or ">" in position one.

REPLIES

After the dialog will come the replies. Replies all start with a greater than sign ">" in position one. Followed by a target, followed by a colon, then by the text of the reply. The target is the dialog topic you want to go to next.

Code: Select all

>name:What is your name
So in the above reply, the target is "name", and the display field is "What is your name" "What is your name" will be displayed in the reply area, and if the user clicks on it, the dialog will move to the "name" topic.

There is one special target, "end", that does NOT go to another dialog topic, instead it closes the formspec and ends the conversation.

ADDING MORE TOPICS

Of course, every "target" in a reply must have a corresponding topic to go to. So lets expand our dialog with another topic:

Code: Select all

===Start
Shiver me timbers, but you caught me by surprise matey!
What be ye doin here?  Arrrgh!  This be no fit place for land lubbers!

>name:What is your name
>arrg:Why do pirates always say Arrrgh?
>treasure:I'm looking for treasure.  Can you tell me where the treasure is?
>rude:What's got you so cranky?  Did a beaver chew on your wooden leg?
>end:Good bye.

===name
My name be Davey Jones.  Not that it be any business of a bildge rat like you!
>bildge rat:What's a bildge rat?
>arrg:Why do pirates always say Arrrgh?
>treasure:I'm looking for treasure.  Can you tell me where the treasure is?
>rude:What's got you so cranky?  Did a beaver chew on your leg?
Now we have created the "Name" topic. So, if the player clicks on "What is your name" in the start section, the dialog will move to the "name" section and display that. You keep adding topics until every possible path through the dialog has a dialog topic for it. It is very important that you do NOT have reply targets that do not actually match up with a dialog topic. If you do, your dialog will not work.

WEIGHTED TOPICS

It is possible to have multiple topics with the same topic name. When you do that, simple_dialogs will chose randomly which topic is shown. Example:

Code: Select all

===Start
I am the mystic of the temple.  Do you have a question?
>dragon:Where does the dragon live and how can I defeat him?
>end:No thank you, I'm just looking around.

===Dragon
You do not appear wise enough to handle the answer to that question.
>start:I really need to know the answer though!
>end:Oh well, good bye then!

===Dragon
You ask the wrong questions.  Go and gain more wisdom first, perhaps study with the master of trees in the crystal forest, then come and ask again.
>start:I dont have TIME to go find another mystic, I need to know now!
>end:I will go and seek for more knowledge then.

===Dragon
Hmmm, I think you are foolish to ask this question, but wisdom comes through hard trials.
The dragon lives on the black mountain in the land of the elves.  As for how to defeat him?  Ask the elves.
>end:Thank you!
So in the above dialog, if the player clicks on "Where does the dragon live and how can I defeat him?" He will get one of three possible responses randomly. Each just as likely to come up as the others.

BUT, what if you wanted to change the odds of which topic shows up? Well, that is actually quite easy to do. You just add a weight (in parenthesis) after the topic name. like below:

Code: Select all

===Dragon(4)
You do not appear wise enough to handle the answer to that question.
>start:I really need to know the answer though!
>end:Oh well, good bye then!

===Dragon(3)
You ask the wrong questions.  Go and gain more wisdom first, perhaps study with the master of trees in the crystal forest, then come and ask again.
>start:I dont have TIME to go find another mystic, I need to know now!
>end:I will go and seek for more knowledge then.

===Dragon(1)
Hmmm, I think you are foolish to ask this question, but wisdom comes through hard trials.
The dragon lives on the black mountain in the land of the elves.  As for how to defeat him?  Ask the elves.
>end:Thank you!
so, in the above example, the first "dragon" topic has a weight of 4, the second 3, and the last one 1. When going to the dragon topic, simple_dialogs will roll a random number between 1 and 8 (4+3+1=8) If the number comes up 1-4, the first Dragon topic will show. If it comes up 5-7, the second topic will show. And only if the number comes up 8 will the last topic show.

VARIABLES

You can use variables in your dialogs. Variables should be enclosed in at sign brackets, like this: @[playername]@ Variables are not case sensitive, and all characters other than letters, numbers, underscore, dash, and period are stripped out. So @[PlayerName]@, @[playername]@, and @[Player Name]@ are all the same.

The variable playername is set by simple_dialogs and will always be available. Other variables may be set by the entity mod using simple_dialogs. Such as @[NPCNAME]@ or @[Owner]@ And you can set your own variables (more on that later)

An example of using a variable in a dialog:

Code: Select all

===Start
Hello @[playername]@.  I am the wizard Fladnag.  I forsaw that you would come to see me today.
>tower:Tell me about your tower please?
>spell:Will you cast a spell for me?
>end:I prefer not to meddle in the affairs of wizards, for they are subtle and quick to anger.
When the above dialog is displayed @[playername]@ will be replaced by the actual playername.

COMMANDS

For more advanced simple_dialogs you can add commands. commands start with a colon ":" in position one. Commands can be anywhere within the topic that makes sense to you. I usually put them between the dialog and the replies. They will be executed in the order they appear, BEFORE anything else is displayed. So you can set any variables in commands and expect them to be populated correctly in that topics dialog or replies.

Commands that are currently supported are

SET

:set variablename=value

This lets you set your own variables. Some examples of the command in use:

:set angry=Y

:set friendlist=|Joe|SallyMiner|BigBuilder|

:set myname=@[npcname]@

Note that we enclosed npcname in at brackets, and we did NOT enclose myname in at brackets. That is because we want the VALUE of the variable npcname to be placed into the variable myname. If we had said :set myname=npcname then myname would be equal to the string "npcname"

An important note about set and compound variables: In a multiplayer game, remember that the variables for an npc are global. If you want to create a variable that is player specific, create a compound variable with the playername as the first part. For example:

:set @[playername]@.trust=High

sets a variable "trust" that would be DIFFERENT for every player. For example, if the players name is singleplayer, the actual variable set would be singleplayer.trust To access the content of that variable you would use this format: @[@[playername]@.trust]@ (it will process the inner brackets first and populate the playername, then process the outerbrackets and get the stored variable)

GOTO

:goto topic

This is very simple, it just allows you to go to another topic. This means that if you have a :GOTO command in a topic, that topic will NEVER be seen, because the commands are always executed first and the goto command will move to another topic. You can only nest gotos 3 levels deep, so there is no risk of getting stuck in a goto loop. While there ARE reasons to use a goto command directly in a dialog, it is most often used in conjunction with the :if command.

HOOK

Hook commands allow you to do things that are outside the purview of simple_dialogs, but have been allowed and coded by the entity mod. For example, a hook might allow an npc to teleport you:

:HOOK Teleport 5000,3,2132

or a hook might allow the npc to trade:

:HOOK TRADE

But the implementation of hooks is entirely up to the entity mod that is using simple_dialogs. (As is the security around them!)

IF

:if (cond in parents) then cmnd

The condition for if has to be enclosed in parenthesis. the cmnd that follows the "THEN" can be any cmnd simple_dialogs can process. SET, GOTO, HOOK, or even another if, although there is no logical reason to do that.

Examples:

:if (@[hunger]@>3) then goto feedme

:if (@[playername]@==@[owner]@) then set greeting=Hello Boss!

:if ( (@[angry]@==N) and (isInList(FriendList,@[playername]@)) ) then set friendstatus=You are my very best friend!

You probably noticed the function isInList() in there, more on that later. Some important things to remember about :If you MUST include the command name to be executed after the "THEN". then greeting=Hello Boss! will NOT work. It has to be then set greeting=Hello Boss! And do not forget to enclose the if condition in parenthesis. You can nest parenthesis as deeply as you wish, but the entire condition must be enclosed in parenthesis.

Note that there is no ELSE functionality. We may add that in the future.

FUNCTIONS

Several functions are available for you use. These can be used in commands OR directly within a dialog

FIRST A NOTE ON LISTS

functions add, rmv, isInList, and notInList all work on list that contain strings surrounded by vertical bars. So, for example a list of pets might look like |dog|cat|mouse|parakeet| As long as you are using the above mentioned functions to deal with the list, you don't need to worry about the vertical bars. They will be added for you.

ADD()

add(variablename,stringtoadd)

Adds a new element to a list, if that element is not already in the list.

Examples:

:set FriendList=add(FriendList,@[playername]@)

:set petlist=add(petlist,alligator)

RMV()

rmv(variablename,stringtoremove)

Removes an element from a list

Examples:

:set FriendList=rmv(FriendList,@[playername]@)

:set petlist=rmv(petlist,mouse)

isInList()

isInList(variablename,stringToLookFor)

Returns true if stringToLookFor is contained in the list in variablename. (surrounded by vertical bars)

Examples:

:if (isInList(friendlist,@[playername]@)) then goto friendly

:if (isInList(petlist,hippo)) then set petresponse=And you can see my friendly hippo over in the mud pond.

notInList

notInList(variablename,stringToLookFor)

this is just the opposite of isInList

Examples:

:if (isNotInList(friendlist,@[playername]@)) then goto enemy

:if (isNotInList(petlist,hippo)) then set petresponse=Do you have a hippo? I need one.

isSet()

isSet(variablename)

This returns true if the variable variablename exists for this npc and is not empty.

Example:

if (isSet(npcname)) then set myname=@[npcname]@

isNotSet()

isNotSet(variablename)

This is the opposite of isSet and returns true if the variable variablename does NOT exist for this npc, or is empty.

Example:

if (isNotSet(npcname)) then set myname=Guido

yesno()

yesno(input)

When input is "0" or "N", this will return "No"

When input is "1" or "Y", this will return "Yes"

It is useful for displaying function results or variables directly in a dialog. Do NOT use this in an If statement, since that expects "1" or "0"

Examples:

Am I angry? yesno(@[angry]@)

Are you in my friendlist? YesNo(isinlist(FriendList,@[playername]@))

timeOfDay()

timeOfDay() returns a value of hours.millihours

so 5:30 will be returned as 5.50 and 15:45 will be returned as 15.75

timeOfDay(NIGHTORDAY) or timeOfDay(DAYORNIGHT) will return 0 for night, and 1 for day

The function defines day as beginning at 4.75 (4:45) when the sun rises

and day as ending at 19.36 (19:22) when the sun sets

calc()

calc(stringOfMath)

This function does math on input strings.

Examples:

:set value=calc(2*(12/4)+1)

:set buyat=calc(@[gold]@*2)

WARNING: Variables by name or reference

Be careful about referencing variables to be clear whether you want the variable name (literal) or the variable value (in at brackets) So, for example:

:set myname=Long John Silver

will set the variable myname to the value "Long John Silver"

but this:

:set myname=Long John Silver

:set @[myname]@=Calico Jack

Will first replace myname with whatever value is in there. Which is "Long John Silver" And THEN execute the set command, so in the end it would actually be doing:

:set LONGJOHNSILVER=Calico Jack

When you want to reference a variable name, do not use at brackets. When you want to replace a variable with it's value, use at brackets.

CONCLUSION

Combining topics, commands, and replies can allow you to create some really complex simple_dialogs. (yes, just wallow in the oxymoron and enjoy it!) You can find some example dialog scripts in the simple_dialogs mod folder.
They are all have names in the format of sd-*.txt
https://github.com/Kilarin/simple_dialogs
https://github.com/Kilarin/simple_dialo ... -guard.txt
https://github.com/Kilarin/simple_dialo ... pirate.txt
https://github.com/Kilarin/simple_dialo ... st-npc.txt



====================
Integrating simple_dialogs with an entity mod (expand the spoiler for details)

Spoiler
simple_dialogs is NOT a stand alone entity mod. It just does the dialogs. It needs to be integrated into an existing entity mod.
So, how do we do that?


First, of course, you need to add simple_dialogs to your entity mods depends.txt as a soft dependency:

Code: Select all

smart_dialogs?
Now, we start by detecting whether simple_dialogs exists (the entity mod should run fine without simple_dialogs) To do that, add the following near the top of your entity mod:

Code: Select all

local useDialogs="N"
if (minetest.get_modpath("simple_dialogs")) then
  useDialogs="Y"
end
We will be adding some more here later, but this is enough for now.

Add simple_dialog controls to the NPC right click menu

There are two simple_dialogs right click menus. One for the simple_dialog controls, where the owner can create and test a dialog. And another for non-owners where we actually display the dialog conversation to another player. Both are pretty easy to add. But there are two ways to do it, depending on whether your entity already has a right click menu for owners or not. (the following examples are from testing with TenPlus1's mobs_redo mobs_npc entity mod)

If the entity mod does not already have a right click menu for owners

Just add the simple_dialogs right click menu, something like this:

Code: Select all

  on_rightclick = function(self, clicker)
    self.id=set_npc_id(self)  --you must set self.id to some kind of unique string for simple_dialogs to work
...
  -- if simple_dialogs is present, then show right click menus
  if useDialogs=="Y" then
    if self.owner and self.owner == name then
      simple_dialogs.show_dialog_controls_formspec(name,self)
    else simple_dialogs.show_dialog_formspec(name,self)
    end --if self.owner
  end --if useDialogs
simple_dialogs will take care of the register_on_player_receive_fields for you.

if the entity mod already has a right click menu for owners

Then you just want to add the simple_dialogs contols to your already existing formspec. And this is actually pretty easy to do:

Here is an example of an existing right click npc owner menu that has simple_dialogs controls added to it:

Code: Select all

function get_npc_controls_formspec(name,self)
  ...
  -- Make npc controls formspec
  local text = "NPC Controls"
  local size="size[3.75,2.8]"
  if useDialogs=="Y" then size="size[15,10]" end
  local formspec = {
    size,
    "label[0.375,0.5;", minetest.formspec_escape(text), "]",
    "dropdown[0.375,1.25; 3,0.6;ordermode;wander,stand,follow;",currentorderidx,"]",
    "button[0.375,2;3,0.8;exit;Exit]"
    }
  if useDialogs=="Y" then simple_dialogs.add_dialog_control_to_formspec(name,self,formspec,0.375,3.4) end
  table.concat(formspec, "")
  context[name]=npcId --store the npc id in local context so we can use it when the form is returned.  (cant store self)
  return table.concat(formspec, "")
end
Note that only two lines (the bolded ones) had to be added here. We changed the size to accomodate the new controls, and just used add_dialog_control_to_formspec to add the dialog controls to the existing formspec. Our final on_rightclick function looks very similar to the one where we did not have an existing owner formspec:

Code: Select all

  on_rightclick = function(self, clicker)
    self.id=set_npc_id(self)  --you must set self.id to some kind of unique string for simple_dialogs to work
...
    if self.owner and self.owner == name then
      minetest.show_formspec(name, "mobs_npc:controls", get_npc_controls_formspec(name,self) )
    elseif useDialogs=="Y" then simple_dialogs.show_dialog_formspec(name,self)
    end
register a var loader

This next step is enitrely optional. If there are any entity mod variables you want to make available within simple_dialogs, you will need to register a varloader function. And within that varloader function, call simple_dialogs.save_dialog_var to save the value into the npc simple_dialogs variable list.

Here is an example, note that we placed it within the same paragraph where we previously set the useDialogs flag.

Code: Select all

local useDialogs="N"
if (minetest.get_modpath("simple_dialogs")) then
  useDialogs="Y"
    simple_dialogs.register_varloader(function(npcself,playername)
    simple_dialogs.save_dialog_var(npcself,"NPCNAME",npcself.nametag,playername)
    simple_dialogs.save_dialog_var(npcself,"STATE",npcself.state,playername)
    simple_dialogs.save_dialog_var(npcself,"FOOD",npcself.food,playername)
    simple_dialogs.save_dialog_var(npcself,"HEALTH",npcself.health,playername)
    simple_dialogs.save_dialog_var(npcself,"owner",npcself.owner,playername)
  end)--register_varloader
end --if simple_dialogs
register any hook functions

Hook functions let you add further functionality to simple_dialogs. The below example allows npc's who's owner has the teleport priv, to teleport players during a conversation. Again, we place this within the same paragraph where we previously set the useDialogs flag.

Code: Select all

local useDialogs="N"
if (minetest.get_modpath("simple_dialogs")) then
  useDialogs="Y"
    ...
    simple_dialogs.register_hook(function(npcself,playername,hook)
    if hook.func=="TELEPORT" then
      if npcself.owner then
        --check to see if the npc owner has teleport privliges
        local player_privs = minetest.get_player_privs(npcself.owner)
        if player_privs["bring"] then
          --validate x,y,z coords
          if hook.parm and hook.parmcount and hook.parmcount>2 then
            local pos={}
            pos.x=tonumber(hook.parm[1])
            pos.y=tonumber(hook.parm[2])
            pos.z=tonumber(hook.parm[3])
            if pos.x and pos.y and pos.z and
              pos.x>-31500 and pos.x<31500 and
              pos.y>-31500 and pos.y<31500 and
              pos.z>-31500 and pos.z<31500 then
              local player = minetest.get_player_by_name(playername)
              if player then
                player:set_pos(pos) end
            end --if tonumber
          end --if hook.parm
        end --if player_privs
      end --if npcself.owner
    return "EXIT"
    end --if hook.func
  end)--register_hook
end --if simple_dialogs
Another good example of a hook might be to initiate a trade dialog. Or even to switch the npc into hostile mode and cause it to start attacking.
simple_dialogs do not allow players to actually change anything outside of the dialog itself. Which makes it quite secure. Hooks let the entity mob give npcs more interactive things they can do. But the security of that function rest entirely upon the entity mod.
Hooks can be designed to either terminate a dialog when done, or to let it continue.

And that is all there is to it!

Simple_Dialogs has already been integrated with TenPlus1's mobs_npc mod: https://notabug.org/TenPlus1/mobs_npc, so that is an excellent place to look for an example.

====================
The Security Of simple_dialogs

I have attempted to make simple_dialogs VERY secure. The players have no access to lua. The calc function DOES make use of loadstring. But before loadstring is run, the input string is filtered to remove characters except for numbers and the characters ".+-*/^()". Furthermore, the call to loadstring is sandboxed so that it has no access to any lua functions outside of loadstring itself. I believe this should keep the function quite secure. If anyone knows otherwise, PLEASE let me know.

I've also tried to code simple_dialogs to be crash proof. Bad formating in a dialog should NEVER cause a server crash. It should just result in a dialog that doesn't actually do anything. Load the dialog in the file sd-test-npc.txt into an npc and run through the tests there. It should NOT crash on any of them.

====================
What still needs to be done?

I don't think I have properly integrated intllib for translating. Any help on that would be greatly appreciated.

Right now simple_dialogs gives very little feedback about poorly formated dialog strings. If you mess up the dialog, things just get dropped and you have to figure out for yourself why. Some kind of feedback to the player telling them what part of their dialog was flawed would be useful.

The parser that simple_dialogs uses is rather primitive. It doesn't handle quotes, and it has no way to escape special characters. Now, in general, this doesn't matter. It's just a dialog processor, its pretty unlikely anyone will be stretching it to the point that these things matter. BUT, there is certainly room to improve it.

The :if command could probably use an else statement. It's not necessary, but it would be nice.

I considered adding a "comment" indicator. It would be very easy, but I'm not certain how useful it would be.

The formspec is functional, but rather boring. If someone wanted to help me spice it up I would be grateful.

Lots of testing and feedback would be greatly appreciated. It is, of course, VITALLY important that no malformed dialog be able to crash the server.

====================
Credit Where Credit Is Due

I was about half-way through this project, and struggling with the gui. I wanted the player to be able to see the npc while they were talking to them. This required either putting the formspec on one side, which left it more narrow than I wanted for replies. Or I could stretch the dialog formspec across the bottom half of the screen, which was great for replies, but didn't look very good for the npc's part of the dialog.

So, I decided to take a break and log on to a multi-player minetest server and just PLAY for a while. I had been on the "Your Land" server in the past, but only briefly. This time I spent a bit more time exploring and discovered that they already had npc's with dialogs! Theirs, I believe, operate via a lua api, so I think they are very different from this code. But one thing I really noticed was their gui. They were using a transparent background for the formspec so that they could have the npc dialog part of the formspec off to one side, and the replies down below. I didn't even know that was POSSIBLE. So, I went back to work on my mod, figured out (with some help on the forum) how to do a formspec with a transparent background, and thus you get the formspec in it's current form. I've never seen the code for the npcs that is used on Your Land, and I don't even know who the coder is that I should credit, but I definitly borrowed a design element from them, and so, Thank you!
EDIT: Sokomine informs me that Bastrabun/AliasAlreadyTaken created the YourLand NPC dialog mod. So, thank you and credit to Bastrabun/AliasAlreadyTaken!

====================
License

This code is licensed under the MIT License
Last edited by Kilarin on Tue Sep 19, 2023 02:00, edited 5 times in total.

Bastrabun
Member
Posts: 211
Joined: Mon Nov 04, 2019 19:48

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Bastrabun » Post

Aloha. Should you happen to stop by your land again, we'd like to invite you to the testserver to see the admin interface of the current version (and whatever else you want to see).
Whatever I say is CC0

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

Thank you kindly for the invitation! I'll take you up on that sometime.

User avatar
apercy
Member
Posts: 640
Joined: Wed Mar 25, 2020 16:31
GitHub: APercy
In-game: APercy
Location: Pinheiral - RJ - Brazil

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by apercy » Post

Hi! I have a suggestion! I did it on my fork of mobs NPC, but I believe your mod could do it better. A command to the mob to open a door or activate a control, when it receive an specific item or simply when asked to do

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

apercy wrote:A command to the mob to open a door or activate a control, when it receive an specific item or simply when asked to do
absolutely possible. It can be implemented as a "hook" in mobs_npc that simple_dialogs calls.
I am hoping to work on a trade hook, I'll add "open door" or "activate control" to the list.
OR, please feel free to convert your own code into a hook and have a pull request!

Of course, this brings up a good question. I designed simple_dialogs to have all non-dialog functionality in the entity mod and called through the register_hook method. That puts the security issues on the entity mod and allows it to make decisions about what actions should and should not be allowed.
Is there a better way to do this?

User avatar
apercy
Member
Posts: 640
Joined: Wed Mar 25, 2020 16:31
GitHub: APercy
In-game: APercy
Location: Pinheiral - RJ - Brazil

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by apercy » Post

Kilarin wrote:
Thu Jun 09, 2022 21:29
...
Of course, this brings up a good question. I designed simple_dialogs to have all non-dialog functionality in the entity mod and called through the register_hook method. That puts the security issues on the entity mod and allows it to make decisions about what actions should and should not be allowed.
Is there a better way to do this?
Good question. Maybe the problem could be when someone uses modified clients and try to submit arbitrary formspecs

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

APercy wrote:Maybe the problem could be when someone uses modified clients and try to submit arbitrary formspecs
SHOULDN'T be. I hope anyway. I put a lot of effort into making certain that arbitrary formspecs can't violate security through simple_dialogs. context is stored on the server, and nothing in the formspec can trigger anything other than an existing and available reply.

User avatar
apercy
Member
Posts: 640
Joined: Wed Mar 25, 2020 16:31
GitHub: APercy
In-game: APercy
Location: Pinheiral - RJ - Brazil

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by apercy » Post

Kilarin wrote:
Thu Jun 09, 2022 22:47
APercy wrote:Maybe the problem could be when someone uses modified clients and try to submit arbitrary formspecs
SHOULDN'T be. I hope anyway. I put a lot of effort into making certain that arbitrary formspecs can't violate security through simple_dialogs. context is stored on the server, and nothing in the formspec can trigger anything other than an existing and available reply.
So Hakuna Matata!!!!!

Sokomine
Member
Posts: 4276
Joined: Sun Sep 09, 2012 17:31
GitHub: Sokomine
IRC: Sokomine
In-game: Sokomine

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Sokomine » Post

It happened again - diffrent people working on a similar problem and comming up with a comparable solution at roughly the same time :-)

I've been planning to write a mod to talk to NPC for several years now. Then I was pointed to the Your Land server and found a mod that was already pretty useful - except that that mod was in no way fit to be handed out to players. So I started working on it. And now I wanted to start integrating the common mobs_npc into it - and found your simple_dialogs in the code. What a (positive) surprise!

While our two mods do roughly the same, the individual approach is pretty diffrent. Yours here works with config files and invents its own language (probably close to other languages used by similar mods?), while my approach is more like a formspec-based editor and allows to click your NPC dialogs together.
Kilarin wrote: So, I decided to take a break and log on to a multi-player minetest server and just PLAY for a while. I had been on the "Your Land" server in the past, but only briefly. This time I spent a bit more time exploring and discovered that they already had npc's with dialogs!
Yes :-) Same here. Sadly the server isn't introduced here on the forum. Its admin didn't want to draw established players over but was rather trying to seek new players from outside and make them learn about the game.
Kilarin wrote: Theirs, I believe, operate via a lua api, so I think they are very different from this code.
In the end we all use the lua api to interact with the game. Internally, the mod on YL uses a data structure that's saved as a .json file.
Kilarin wrote: But one thing I really noticed was their gui. They were using a transparent background for the formspec so that they could have the npc dialog part of the formspec off to one side, and the replies down below. I didn't even know that was POSSIBLE. So, I went back to work on my mod, figured out (with some help on the forum) how to do a formspec with a transparent background, and thus you get the formspec in it's current form. I've never seen the code for the npcs that is used on Your Land, and I don't even know who the coder is that I should credit, but I definitly borrowed a design element from them, and so, Thank you!
Same here. My original plan was to use the HTML based elements to have the replies act as links. The praise for structuring the formspec the way we both use it now goes to Bastrabun/AliasAlreadyTaken.

In a way Bastrabun/AliasAlreadyTakens mod is more powerful than either of our mods can (or ought to) ever be: It allows to execute lua code. Which is the reason why the version running on the server can't be opened for players and my version is necessary.

This is how an option (answer) is edited in my mod in the complex version, if you want to have more than just the text and diffrent answers/options/replies:
fs_edit_options.png
fs_edit_options.png (114.78 KiB) Viewed 4782 times
The overall functionality may end up to be relatively similar - with either mod having more in one area than the other and vice versa.

How the things we deal with are called varies a lot. Your "Topics" are "dialogs" in the YL version, "replies" are "options"/answers, weighted topics/random answers don't exist yet in my version (though they do in the original one), general variables like npc name etc. are enclosed in $ in my version, variable handling is very formspec-based and needs a bit more work.

I wonder if eventually a translation between the save file formats of our mods will be possible or useful.
A list of my mods can be found here.

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

Sokomine wrote:It happened again - diffrent people working on a similar problem and comming up with a comparable solution at roughly the same time
Ha! Synchronicity! It DOES seem to happen a lot.
Sokomine wrote:The praise for structuring the formspec the way we both use it now goes to Bastrabun/AliasAlreadyTaken.
Thank you! I'm glad to be able to give credit!
Sokomine wrote:In a way Bastrabun/AliasAlreadyTakens mod is more powerful than either of our mods can (or ought to) ever be: It allows to execute lua code. Which is the reason why the version running on the server can't be opened for players and my version is necessary.
Yes, exactly. We were both thinking the same thing. That there ought to be a simple way to let the players create dialogs for their npcs without giving them all the powers of lua. :)
Sokomine wrote:while my approach is more like a formspec-based editor and allows to click your NPC dialogs together.
Wow! That looks really nice! And powerful! You always do EXCELLENT work.
Sokomine wrote:I wonder if eventually a translation between the save file formats of our mods will be possible or useful.
That would be cool to do. So far though, I haven't seen any actual interest in my mod. So there might not be any market for the transfer tool. :) I hope your mod will attract more attention, because I think users being able to set up npc dialogs would really add to the immersive feel of the world!

Sokomine
Member
Posts: 4276
Joined: Sun Sep 09, 2012 17:31
GitHub: Sokomine
IRC: Sokomine
In-game: Sokomine

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Sokomine » Post

Kilarin wrote: Ha! Synchronicity! It DOES seem to happen a lot.
Wouldn't be MT without :-)
Kilarin wrote: That would be cool to do. So far though, I haven't seen any actual interest in my mod. So there might not be any market for the transfer tool. :) I hope your mod will attract more attention, because I think users being able to set up npc dialogs would really add to the immersive feel of the world!
I hope your mod will attract more attention as well. Have you put it on contentdb? I think the forum is used far less by players nowadays to get information about new mods. They use the contentdb. It's important that it's listed there.

It might also help to search for a server that can host the mod so that players can get into contact with it. It's fine to have NPC in your singleplayer world, and if you're designing a game (which very few people do), then it helps a lot as well. But the real power comes from having the NPC on multiplayer servers and adding life to your buildings there :-)

My NPC can also act as traders. They have an inventory and can make multiple trade offers. I hope that'll reach those players who are not so much into roleplaying.

The Your Land server has that RPG background with the mysterious "Voice" attacking our cities, and there are regular events and even small quests. But even there not all players participate. Still, those who do are eager to get their own NPC :-)
A list of my mods can be found here.

Gorm
Member
Posts: 29
Joined: Tue Feb 14, 2023 17:06

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Gorm » Post

Hello!

First time seen. No idea whats going on.

Code: Select all

2023-03-20 15:01:41: ACTION[Server]: Imperior right-clicks object 2271: LuaEntitySAO "dach:citizen_f" at (-10,20,5)
2023-03-20 15:01:46: ACTION[Main]: Server: Shutting down
2023-03-20 15:01:46: ACTION[Server]: Gorm leaves game. List of players:
2023-03-20 15:01:46: ACTION[Server]: Imperior leaves game. List of players:
2023-03-20 15:01:47: ERROR[Main]: ServerError: AsyncErr: Lua: Runtime error from mod 'simple_dialogs' in callback on_playerReceiveFields(): ...test/minetest-master/bin/../mods/simple_dialogs/init.lua:1367: attempt to index a nil value
2023-03-20 15:01:47: ERROR[Main]: stack traceback:
2023-03-20 15:01:47: ERROR[Main]:       ...test/minetest-master/bin/../mods/simple_dialogs/init.lua:1367: in function 'func'
2023-03-20 15:01:47: ERROR[Main]:       ...etest-master/bin/../builtin/profiler/instrumentation.lua:108: in function <...etest-master/bin/../builtin/profiler/instrumentation.lua:101>
2023-03-20 15:01:47: ERROR[Main]:       ...inetest/minetest-master/bin/../builtin/game/register.lua:446: in function <...inetest/minetest-master/bin/../builtin/game/register.lua:432>
Yours Gorm

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

Hello Gorm!
Can you either paste here or message me the conversation script that this crashed on pretty please?
Also, do you happen to know where you were in the conversation tree and what you clicked on when it crashed?

Gorm
Member
Posts: 29
Joined: Tue Feb 14, 2023 17:06

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Gorm » Post

Hello Kilarin!

I was not on when that happens and the server simply rebooted.

Code: Select all

===Start
Hello @[playername]@ i'm Clara. What do ya want to know?
>npcs: Tell me more about NPCs.
>location:Where is a good place to settle?
>shops: Where can i buy goods like food?
>end:Good bye!

===location
Go to the west gate and follow the road there up to the hill. But beware there are scorpions in the desert and they are extremly dangerous. 

Better you walk there trough the night. Up on the hill you can follow the road further and you will find many places to settle.

Else you can go north. At the first part of the road there are also scorpions and other monsters. 

But if you follow that road it leads to more good places to settle. 

There is a crystal wood near the end of that road but it is under protection. But maybe there are little parts freely accessible.
>Start: I've another question.
>end: Good bye!

===npcs
Well many of them here at spawn are simple cityguards. They dont have much to say.

But others maybe tell you interesting things about adventures or treasures. They possibly can give you hints about other NPCs that know even more about adventuring. Its always a good idea to talk to the NPCs. 

There are also NPCs like the smith and the horse dealer. They both have shops and sell goods from their work.
>Start: I've another question.
>end: Good bye!

===shops
Well there is a smith selling ironwork and a horse dealer. 

Behind me is the house of Ortwin the local trader of many different foods. But pss he is not very cheap.

Or you can go to the market. Follow the westroad and you will see it. There are a lot of different traders who sell local goods to anyone. Farmers or there partners. You can also get vanison from the rangers there.
>Start: I've another question.
>end: Good bye!
Thats a very simple dialog. And i have no problems at all. There are more then 20 NPCs around. All with more or less that amount of dialog. This was the first time and i only saw it because wondering about the short uptime from server. So looking at the log and found that error message.

I like your mod very much and i'm only scratching at the surface of it. I planned a lot more but its slowly evolving. Not enough time for it. These dialogs bring much more live towards the game. I wrote some RPG Storys but my programming skills are lousy. They are also slowly evolving. But your mod is a fundamental piece for my story driven gameplay.

Yours Gorm

ps Server is minetest-5.7-rc1 on Debian Gnu-Linux

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

I'm baffled. I'll dig into it and see if I can figure out what happened. Thank you!

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

Thank you for you patience, and my deepest apologies for the crash.

The only way for that particular line of code to crash with that error is when the reply index returned is out of range. That should be impossible. The only way I was able to reproduce it was to hardcode an override to make the index out of range.

So, I have no idea how that value slipped through and caused the crash, but the code should have been written defensively to resist that kind of error anyway. I just pushed a change that does exactly that.

https://github.com/Kilarin/simple_dialogs (version 0.2)

Update with this code, and you should not see this crash again. If, for completely inexplicable reasons, the reply index returned when the user clicks is out of range, then the mod just prints an error message to the log and closes the formspec. WITHOUT crashing.

Thank you very much for finding this bug and reporting it!

I didn't realize anyone was using simple_dialogs, so I'm very glad to see that it is helping somewhere!
What server are you running this on?

Gorm
Member
Posts: 29
Joined: Tue Feb 14, 2023 17:06

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Gorm » Post

Hello Kilarin!
Thanks for your time and effort to write this mod and surely for fixing that bug. :-)

Oh my server is "Ancient Times". Its in the list far down ;-)
Glad if you visit there. Its in early stage but there are already a few players.
Learning lua and all that stuff eg. models for mobs or NPCs and doing textures for them takes time.
I expect to go public end of this year.
Want to use your mod for RPG stuff. The hooks and the vars are a bit more work. Learning slowly but steady.

Sorry for my english its not the best. :-)

Yours Gorm

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

Gorm wrote:Sorry for my english its not the best.
Your English is fine! If you need help with coding dialogs, feel free to post your ideas here and I'll be happy to help turn them into scripts.

Gorm
Member
Posts: 29
Joined: Tue Feb 14, 2023 17:06

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Gorm » Post

Hello Kilarin!

Thanks for the generous offer.
Today I was writing one of the quests and I had several questions:
1. Can you query the time of day (just whether it's day or night) with an if? Inside the dialog.
2. Can I give an item to a player? I assume via HOOK?
3. Can I query if a player has a specific item in their inventory? Also via a HOOK?

Or is that possible via the varloader i don't think so because the vars from there are only for the NPC, right?

I now know how to use the if and i am able to store values and make decisions on these stored values. Fine possibility.

I looked at the "if" functionality and wrote a dialog with it. Values ​​are saved based on the answers and the player is then presented with different additional questions and answers based on the saved values.

I don't want to post that dialog here because then everybody knows the right answers for this little adventure. ;-)

Have a nice Sunday!
Yours Gorm

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

Are you using TenPlus's mobs_npc, or have you integrated with a different mobs mod?
Gorm wrote:Can you query the time of day (just whether it's day or night) with an if? Inside the dialog.
That is not currently written in the code. But realistically, it could probably be added without violating the design. I can't think of any reason this should be limited to a HOOK. I'm kinda buried under with work, but this should be pretty simple to add. I'll look into it.
Gorm wrote:Can I give an item to a player? I assume via HOOK?
Giving an item to a player would require a hook to be written. And there are two reasons for that
1: If you want the npc to be able to give an item out of their own inventory, then yep, we require a hook to the mob control mod, because the mod control mod controls the mobs inventory.
2: If you want the npc to be able to give away infinite copies of a particular item (like in creative mode), then even though this would not involve the inventory, it will still require a hook, because anything NOT limited to a hook is available for any player to write into a dialog. And you don't want just any player to be able to create an npc that gives away unlimited steel bars. :)
Gorm wrote:Can I query if a player has a specific item in their inventory? Also via a HOOK?
You could certainly do it via a HOOK. BUT, since it's player inventory, not npc inventory, I'm not certain it should REQUIRE a hook. I'm trying to think if there are security reasons it would be bad to allow any npc to do a get_inventory() on any player that clicks on them? I mean, obviously this is not a risk when they are npc's set up by the admin. But if I built this directly into simple_dialogs it would allow player owned npc to snoop on the full inventory of anyone who clicked on them. Is that ok? I'll need to think about that one.

Feel free to PM me if you want me to look over any specific dialog you are having trouble with without exposing it to the public eye. (And feel no obligation to do so if you prefer to keep them entirely private, I completely understand that)

Gorm
Member
Posts: 29
Joined: Tue Feb 14, 2023 17:06

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Gorm » Post

Hello Kilarin!
Yes i'm using TenPlus1's mobs_npc. A good stable base. And he is always helping noobs like me with their code.

Thanks for looking into the day night thing. I tried it myself and failed.

The other two parts you're right. But in my world only i spawn NPCs. But HOOKs are on my todo list.

This week i try to make some more models for the NPCs. 2 are ready but i need 3 more. I need them for my formspec where i can deploy NPCs and chose the skin, tools and so on. As always this takes a lot of time ;-)
eg. i want a guard with a halberd and there is no model for it. Also sometimes i can see the shield part from the b3d so i made a model without that part. So that it only carries a sword.

Thanks for your help!
Yours Gorm

chbuilder
New member
Posts: 1
Joined: Sun Jan 30, 2022 16:45

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by chbuilder » Post

Am I understand correctly, that you, Gorm, are working on a formspec to create NPCs programmatically? Would you be interested in sharing the code, i.e. on github or gitlab?

User avatar
Kilarin
Member
Posts: 894
Joined: Mon Mar 10, 2014 00:36
GitHub: Kilarin

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Kilarin » Post

I have added the function timeOfDay()

timeOfDay() returns a value of hours.millihours
so 5:30 will be returned as 5.50 and 15:45 will be returned as 15.75

timeOfDay(NIGHTORDAY) or timeOfDay(DAYORNIGHT) will return 0 for night, and 1 for day

The function defines day as beginning at 4.75 (4:45) when the sun rises
and day as ending at 19.36 (19:22) when the sun sets

That should work for you just fine now.

BUT, I have run into an interesting problem. If I paste dialogs into an npc using gedit, which, presumably, sends them with linux line endings. simple_dialogs chokes on them. It does not crash, mind you, but it seems to detect the entire dialog as one big line instead of as separate lines. So it can't find any of the headers for the topics.
I need a way to make lua process text in a platform independent manner.

User avatar
Blockhead
Member
Posts: 1622
Joined: Wed Jul 17, 2019 10:14
GitHub: Montandalar
IRC: Blockhead256
In-game: Blockhead Blockhead256
Location: Land Down Under
Contact:

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by Blockhead » Post

Kilarin wrote:
Sun Apr 09, 2023 02:18
BUT, I have run into an interesting problem. If I paste dialogs into an npc using gedit, which, presumably, sends them with linux line endings. simple_dialogs chokes on them. It does not crash, mind you, but it seems to detect the entire dialog as one big line instead of as separate lines. So it can't find any of the headers for the topics.
I need a way to make lua process text in a platform independent manner.
Use binary mode when you use file.open, e.g. file.open(minetest.get_worldpath() .. "/path/to/script.whatever", "rb") and standardise on UNIX end of line (or Windows if you really insist). Basically anyone who has written cross-platform file I/O has hit this issue :(
/˳˳_˳˳]_[˳˳_˳˳]_[˳˳_˳˳\ Advtrains enthusiast | My map: Noah's Railyard | My Content on ContentDB ✝️♂

User avatar
LMD
Member
Posts: 1386
Joined: Sat Apr 08, 2017 08:16
GitHub: appgurueu
IRC: appguru[eu]
In-game: LMD
Location: Germany
Contact:

Re: [Mod] Simple_Dialogs for Minetest entities [simple_dialogs]

by LMD » Post

Just use io.lines and call it a day.
My stuff: Projects - Mods - Website

Post Reply

Who is online

Users browsing this forum: No registered users and 16 guests