Post your modding questions here

Hybrid Dog
Member
 
Posts: 2460
Joined: Thu Nov 01, 2012 12:46

Re: Post your modding questions here

by Hybrid Dog » Sun Oct 18, 2015 14:39

Ferk wrote:
Don wrote:Do I serialize the table and then when I read from it I would deserialize? I am not understanding how this works.

Exactly, you basically do this:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
-- serialize an write it
f, err = io.open(filename, "w")
f:write(minetest.serialize(data))
f:close()

-- read it and deserialize
f, err = io.open(filename, "r")
local data = minetest.deserialize(f:read("*a"))
f:close()

You can compress the text using minetest.compress. When you read the file, you need to io.open it with "rb" instead or "r". You can also decompress it of course.
 

Hybrid Dog
Member
 
Posts: 2460
Joined: Thu Nov 01, 2012 12:46

Re: Post your modding questions here

by Hybrid Dog » Sun Oct 18, 2015 14:44

Ferk wrote:I also have a question.. I'm creating a looping sound around a node. For this I use a similar code as it's done in the fire mod:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.sound_play(name, {
         pos = pos,
         max_hear_distance = 6,
         loop = true
      })


However, often the sound continues looping endlessly with the same intensity regardless how far I am from the node.
I actually experience this as well with the fire at times. Is this a bug? If not, what could I be doing wrong?

I noticed that in the wiki it says that a sound has to be "attached" to an object for the looping to work. But I assumed this info is outdated, since it's used in the official fire mod assigned only to a position instead of an object.

EDIT: I did some more testing and it seems that if when the sound triggers (by an ABM) the player is within max_hear_distance, the sound plays in a loop constantly no matter how far I get.. but if sound_play is executed when the player is farther away than max_hear_distance the sound doesn't play at all, even if I then move to be next to the playing position.

What should I do for the sound to dynamically change with the distance from the node?

Maybe your sound is stereo. Stereo sounds aren't handled well, how should stereo behave if the sound comes from one point (the node)?
Often when l use the music box of technic, when l walk away, the music becomes quiet but then, when l walk further away, l can still hear it (fairly quiet).
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Sun Oct 18, 2015 14:57

Hybrid Dog wrote:Maybe your sound is stereo. Stereo sounds aren't handled well, how should stereo behave if the sound comes from one point (the node)?

Thanks! that was it, now it works fine.

It's still noisy when far away though, the sound never seems to completely go away, there's always some faint trace of it resounding in the background, no matter how many layers of wall are between you and the sound.

I reduced max_hear_distance from 6 to 3, and I still can faintly hear it 160 nodes away. Only at about 700 nodes does it stop being noticeable. Is there a way I can mitigate this? Ideally there should be no trace of the sound after a 32 radius.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
Don
Member
 
Posts: 1641
Joined: Sat May 17, 2014 18:40
GitHub: DonBatman
IRC: Batman
In-game: Batman

Re: Post your modding questions here

by Don » Sun Oct 18, 2015 15:08

Thanks for the help.
Many of my mods are now a part of Minetest-mods. A place where you know they are maintained!

A list of my mods can be found here
 

User avatar
mrob27
Member
 
Posts: 21
Joined: Sun Sep 27, 2015 13:32
GitHub: mrob27

Re: Post your modding questions here

by mrob27 » Mon Oct 19, 2015 00:07

rubenwardy wrote:I just see a grey circle with a horizontal bar across it ^

I suggest pasteboard.co or imgcru.sh

I managed to get the images while they were still working. Here they are:
Image

Image

It's great to see these slices of Minetest terrain gen. Is it v6 terrain? Looks like a lot of Nyan Cat on the bottom there...
 

User avatar
iangp
Member
 
Posts: 114
Joined: Sat May 31, 2014 19:26
GitHub: 14NGiestas
IRC: iangp
In-game: iangp

Re: Post your modding questions here

by iangp » Mon Oct 19, 2015 10:47

mrob27 wrote:
rubenwardy wrote:I just see a grey circle with a horizontal bar across it ^

I suggest pasteboard.co or imgcru.sh

I managed to get the images while they were still working. Here they are:
Image

Image

It's great to see these slices of Minetest terrain gen. Is it v6 terrain? Looks like a lot of Nyan Cat on the bottom there...


They are from minetest... and nyan cat rainbow are the Bedrock in MC...
I'm trying build my own MC-MTmap converter in python. Someone already make one... but I've tried but not have mesecons support, and support to other blocks.
These are the result of first "wall" of blocks of my MC map... using a txt file...
God's not dead, He's surely alive!
エル プサイ コングルー

My mods (WIP):
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Tue Oct 20, 2015 18:29

I would like to animate a sprite. Can someone explain this function from LuaEntitySAO?

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2, select_horiz_by_yawpitch=false) — Select sprite from spritesheet with optional animation and DM-style texture selection based on yaw relative to camera


I understand num_frames and I guess select_horiz_by_yawpitch automatically switches the sprite based on the yaw (I guess for doom-like sprites).

If I want a looping animation do I actually need to execute a routine for every single frame? isn't there something like a firelike drawtype? I'm basically implementing a moving fire.

I already defined a initial_sprite_basepos and a spritediv in the definition of the entity I would expect it doesn't need to know the divisions of the sprite and I would have guessed framelength to be a unit of time for the animation, but it doesn't seem to work.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
Don
Member
 
Posts: 1641
Joined: Sat May 17, 2014 18:40
GitHub: DonBatman
IRC: Batman
In-game: Batman

Re: Post your modding questions here

by Don » Tue Oct 20, 2015 19:14

@Ferk - Does this help? It is a program for animating sprites.
http://www.aseprite.org/
Many of my mods are now a part of Minetest-mods. A place where you know they are maintained!

A list of my mods can be found here
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Tue Oct 20, 2015 20:20

Don wrote:@Ferk - Does this help? It is a program for animating sprites.
http://www.aseprite.org/

Oh! that program looks cool.

However, I already have the animation drawn, what I wanted to know is if there's a way to display it in Minetest without having to manually change the sprite texture for each frame in the on_step function of the entity.

The speed in which I need to process stuff for my entity is much slower than the animation (it's an extremely simple mob, just moving between a set of waypoints), so I was hoping for a way to make it client-side. Just like fire, torches and other nodes are animated without the server needing to ask the clients every time to change the texture on each step of the animation.

Maybe this could also be useful for your pacman ghosts (unless you are using a mesh).. I actually got inspired by your idea and started making a simple mob / obstacle / trap for dungeontest as well :)
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
mrob27
Member
 
Posts: 21
Joined: Sun Sep 27, 2015 13:32
GitHub: mrob27

Re: Post your modding questions here

by mrob27 » Tue Oct 20, 2015 23:07

Ferk wrote:I would like to animate a sprite. Can someone explain this function from LuaEntitySAO?

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
 setsprite(p={x=0,y=0}, num_frames=1, framelength=0.2, select_horiz_by_yawpitch=false) — Select sprite from spritesheet with optional animation and DM-style texture selection based on yaw relative to camera


In src/script/lua_api/l_object.cpp we have the lua function:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
 // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
 //           select_horiz_by_yawpitch=false)
  int ObjectRef::l_setsprite(lua_State *L)
  {
    NO_MAP_LOCK_REQUIRED;
    ObjectRef *ref = checkobject(L, 1);
    LuaEntitySAO *co = getluaobject(ref);
    if(co == NULL) return 0;
    // Do it
    v2s16 p(0,0);
    if(!lua_isnil(L, 2))
        p = read_v2s16(L, 2);
    int num_frames = 1;
    if(!lua_isnil(L, 3))
   num_frames = lua_tonumber(L, 3);
    float framelength = 0.2;
    if(!lua_isnil(L, 4))
        framelength = lua_tonumber(L, 4);
    bool select_horiz_by_yawpitch = false;
    if(!lua_isnil(L, 5))
        select_horiz_by_yawpitch = lua_toboolean(L, 5);
    co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
    return 0;
  }

It's just a wrapper for a C function setSprite; this takes us to src/content_sao.cpp :

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
  void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
        bool select_horiz_by_yawpitch)
  {
    std::string str = gob_cmd_set_sprite(
        p,
        num_frames,
        framelength,
   select_horiz_by_yawpitch
    );
    // create message and add to list
    ActiveObjectMessage aom(getId(), true, str);
    m_messages_out.push_back(aom);
  }

thence to src/genericobject.cpp :

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
  std::string gob_cmd_set_sprite(
    v2s16 p,
    u16 num_frames,
    f32 framelength,
    bool select_horiz_by_yawpitch
  ){
    std::ostringstream os(std::ios::binary);
    // command
    writeU8(os, GENERIC_CMD_SET_SPRITE);
    // parameters
    writeV2S16(os, p);
    writeU16(os, num_frames);
    writeF1000(os, framelength);
    writeU8(os, select_horiz_by_yawpitch);
    return os.str();
  }

thence to src/content_cao.cpp :

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
  void GenericCAO::processMessage(const std::string &data)

  // [ ... many lines omitted ... ]

    else if(cmd == GENERIC_CMD_SET_SPRITE) {
        v2s16 p = readV2S16(is);
        int num_frames = readU16(is);
        float framelength = readF1000(is);
        bool select_horiz_by_yawpitch = readU8(is);

        m_tx_basepos = p;
        m_anim_num_frames = num_frames;
        m_anim_framelength = framelength;
        m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;

        updateTexturePos();
    }

CAO is "Client Active Object", i.e. we've passed the setsprite command right through to the client without doing anything on the server.

These variables (m_tx_basepos, etc.) are only ever used to manipulate m_spritenode, which is an Irrlicht object in class irr::scene::IBillboardSceneNode. According to the Irrlicht documentation, this is "A billboard scene node. / A billboard is like a 3d sprite: A 2d element, which always looks to the camera. It is usually used for explosions, fire, lensflares, particles and things like that."

This sounds like just what you want! Unfortunately, there is only one per client, it is a global variable and it is created in src/content_cso.cpp:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
  class SmokePuffCSO: public ClientSimpleObject
  {
    float m_age;
    scene::IBillboardSceneNode *m_spritenode;
public:
    SmokePuffCSO(scene::ISceneManager *smgr,
            ClientEnvironment *env, v3f pos, v2f size):
        m_age(0),
        m_spritenode(NULL)
    {
        infostream<<"SmokePuffCSO: constructing"<<std::endl;
        m_spritenode = smgr->addBillboardSceneNode(
                NULL, v2f(1,1), pos, -1);
        m_spritenode->setMaterialTexture(0,
                env->getGameDef()->tsrc()->getTexture("smoke_puff.png"));
        m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
        m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
        //m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
  // [... etc. ]

There is almost identical code in src/content_cso.cpp, "CSO" is "Client Simple Object". m_spritenode is referenced in a lot of places but it is only ever initialised as a smoke puff. Since there is one per client, it seems it is only ever used for the "you just killed something" animation. That must be what the lua setsprite function does. I can guess that the basepos tells where within the texture the first frame is derived, there are some clues to this in lua_api.txt if you look for "sprite", you'll find spritediv and initial_sprite_basepos mentioned in the object properties along with more familiar things like hp_max and collisionbox.

So if you don't like the smoke puff, you can change it with setsprite, but I doubt you can get this sprite to be used for anything other than showing the result of a kill.

We also find the following in lua_api.txt :

Entity damage mechanism
 […]
Client predicts damage based on damage groups. Because of this, it is able to give an immediate response when an entity is damaged or dies; the response is pre-defined somehow (e.g. by defining a sprite animation) (not implemented; TODO).
Currently a smoke puff will appear when an entity dies.

which pretty much confirms this is what setsprite was intended for.

You might be able to use it to define mobs that are displayed as billboards, i.e. flat cardboard stand-ups like in early versions of Minetest, and if you did that, the mob's 2D appearance could be animated. But I don't see how it could work, since there is only ever one m_spritenode in the client; and we've moved away from that, I think everyone wants their mobs to be 3-D animated now.
Last edited by mrob27 on Wed Oct 21, 2015 00:16, edited 1 time in total.
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Wed Oct 21, 2015 00:14

Thank you mrob27 for the research! :)
This helped me understand a bit more. Imho, the dev.minetest.net wiki should have more links pointing to the actual code. Specially considering how the wiki is often left incomplete or outdated.

You might be able to use it to define mobs that are displayed as billboards,[...]. But we've moved away from that, I think everyone wants their mobs to be 3-D animated now.

Yes, I was actually using drawtype = "sprite". The thing is that it's way harder to obtain a good looking 3-D animated model. Specially if you want to avoid too many polygons. For something as simple as a ball of fire it makes more sense as a billboard. An actual sphere mesh would look out of place, imho.
I wouldn't mind using a 3D cube with textures similar to the fire node, but there's no "firelike" drawtype for entities, I'm not sure how would I animate the texture of the cube.

CAO is "Client Active Object", i.e. we've passed the setsprite command right through to the client without doing anything on the server.

But this is the "processMessage" method of the CAO, and we started in the SAO. I assume there's actually a message sent by the server then for every single change in the sprite. So it looks like there's no way to do the animation client-side without relying on server communication (contributing to lag). I guess nobody cares about this because everyone uses 3D models.

Also I didn't find anything like the "damage_per_second" that nodes have or at least some handler to trigger on collisions. So I guess the only way for an entity to damage a player is to check for players every iteration of the on_step loop (or at least often enough to not miss it), is that right? That doesn't look very efficient, in the end my small entity might turn out heavier than expected.
Last edited by Ferk on Wed Oct 21, 2015 00:33, edited 1 time in total.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
mrob27
Member
 
Posts: 21
Joined: Sun Sep 27, 2015 13:32
GitHub: mrob27

Re: Post your modding questions here

by mrob27 » Wed Oct 21, 2015 00:32

But this is the "processMessage" method of the CAO, and we started in the SAO. I assume there's actually a message sent by the server then for every single change in the sprite. So basically, there's no way to do the animation client-side without relying on server communication (contributing to lag).

I'm pretty new to this, but it looks like the message is sent only once in response to the call of setsprite; and then from that point on the animation of individual frames is handled by GenericCAO::updateTexturePos within the client. So if you don't want lag, you would call setsprite only once.

Also I didn't find anything like the "damage_per_second" that nodes have or at least some handler to trigger on collisions. So I guess the only way for an entity to damage a player seems to be to check for players every iteration of the on_step loop.

Player movement (physics, collisions), and therefore position, must be computed on each player's client, in order to avoid the camera-position lag that would happen if the player's physics were being done on the server. But each object's physics are computed in only one place, because if there is a disagreement what do you do? All non-player objects' physics are computed on the server so that no one player has an unfair advantage, and also to avert many of the loopholes used by cheating hacks. Therefore, there will be lag between each player and every other thing that moves. There is a double-lag in a combat situation between two players. I had a discussion about this with @est31 on Github after discovering the inability to set player velocity was impeding my aspirations for the P0rtalgun.
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Wed Oct 21, 2015 00:44

from that point on the animation of individual frames is handled by GenericCAO::updateTexturePos within the client

Nice, that's exactly what I want. However, it doesn't seem to work. Or at least the texture doesn't update for me after the first setsprite. That's why I asked about the num_frames and framelength parameters of setsprite.. I'm not sure how do I need to set it up. I already have a spritediv={x=3, y=1} defined and I can switch image by manually changing the "pos" parameter in setsprite, but only when I manually request it from the SAO. Maybe someone knows.

each object's physics are computed in only one place, because if there is a disagreement what do you do?

My concern in this case is that I cannot make use of the physics, not even when just running server-side.
I have to manually do a lookup for the players, iterate through all players checking their positions or use "minetest.get_objects_inside_radius" to get the objects around my entity every fraction of a second that I want to damage a player. That's not a good way to do it, imho. Specially if there's already a physics engine checking for collisions, why can't I make use of an "on_collision" handler? This wouldn't only be good for entities but also for nodes (I'm thinking pressure plates, which right now would need an ABM checking for players cyclically as well), the "damage_per_second" of nodes could have been generalized into a "on_collision_step(dtime)", so modders could do more things with the collisions than just damage.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
Don
Member
 
Posts: 1641
Joined: Sat May 17, 2014 18:40
GitHub: DonBatman
IRC: Batman
In-game: Batman

Re: Post your modding questions here

by Don » Wed Oct 21, 2015 01:33

@Ferk- on_collision would make telepirter better to wouldn't it?
Many of my mods are now a part of Minetest-mods. A place where you know they are maintained!

A list of my mods can be found here
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Wed Oct 21, 2015 07:55

@Don exactly, I bet there are many mods that could benefit from it. Also things like areas that heal the player instead of hurting him (the reverse of damage_per_second) or all sorts of traps for adventure maps that are invisible but get activated as soon as the player steps on them.

Having something like this my mob could have been done extremely lightweight without any logic in the on_step loop. Just changing its direction every time it collides with a waypoint node or something else (and if a player, damage it). Without this, now for every single aggressive mob that is loaded the server will necessarily have to do some extra Lua calculations per second. CPU usage could easily escalate when you have several of these loaded at the same time.

Being able to use a waypoint system like that would also have been useful for things like rail carts. And I would guess not having to check/update the velocity or call on_step every cycle would make it easier for client prediction.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
Napiophelios
Member
 
Posts: 752
Joined: Mon Jul 07, 2014 01:14
GitHub: Napiophelios
IRC: Nappi
In-game: Nappi

Re: Post your modding questions here

by Napiophelios » Wed Oct 21, 2015 20:28

I am trying to make a standalone crafting table mod
but I am having trouble with the formspec.

Here is the code I am using:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
   on_construct = function(pos)
      local meta = minetest.env:get_meta(pos)
      meta:set_string("formspec",
   "size[8,9]"..
   default.gui_bg..
   default.gui_bg_img..
   default.gui_slots..
   "list[current_player;main;0,5;8,4;]"..
   "list[current_player;craft;2,0.5;4,4;]"..
   "list[current_player;craftpreview;7,2;1,1;]"..
   "image[6,2;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
   "listring[current_player;main]"..
   "listring[current_player;craft]")
      meta:set_string("infotext", "Crafting Table")
      local inv = meta:get_inventory()
--inv:set_width("craft", 4)
--inv:set_size("craft", 4*4)
  inv:set_size("craft", 16)
   end,

Image
screenshot_20151021.png
screenshot_20151021.png (113.41 KiB) Viewed 2841 times


What can I do to get the full 4x4 crafting grid?
 

afeys
Member
 
Posts: 17
Joined: Thu Mar 26, 2015 08:55

Re: Post your modding questions here

by afeys » Thu Oct 22, 2015 11:37

Hi,

I have 2 questions, which I hope someone can help me answer:

1/ In my mod (pre-alpha version) I place a schematic with minetest.place_schematic() and that works perfectly. However, when I come accross that building in my test world, I can't open the chests. I haven't been able to find a solution for this. Anyone know what could be the problem?

2/ Is there a way for a node to know if someone is stepping on it, or touching it? Ideally there should be an event minetest.register_on_playertouchnode or minetest.register_on_playersteponnode (like minetest.register_on_punchnode) or something like that which triggers when a player is on that block. Even more perfect would be way to know which side of the block the player has touched (by stepping on it, or hitting his/her head on it while jumping below it).

Anyone got any ideas on how to solve these ?

best regards,
Andy
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Thu Oct 22, 2015 11:55

afeys wrote:1/ [...] minetest.place_schematic() [...] I can't open the chests. [...]

Yup, mts files don't store the node's metadata (and the chest inventory / formspec / infotext is metadata). You have to save the metadata to a separate file or use a mod like worldedit or handle_schematics from sokomine.

I also do this in Dungeontest. Maybe I should try to factor out and generalize the dungeon_rooms mod I wrote so it can be used outside of Dungeontest.

afeys wrote:2/ Is there a way for a node to know if someone is stepping on it, or touching it? [...] minetest.register_on_playertouchnode or minetest.register_on_playersteponnode

This is exactly the same as what I was asking for in my last posts in this thread. It doesn't look like such a thing exists... I wish it got implemented, since I think a lot of people want it. The only workaround is to use an abm or a timer and check constantly for players.

I guess you are also making a dungeon mod?
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
Don
Member
 
Posts: 1641
Joined: Sat May 17, 2014 18:40
GitHub: DonBatman
IRC: Batman
In-game: Batman

Re: Post your modding questions here

by Don » Thu Oct 22, 2015 12:53

@afeys - Like Ferk said, the meta data is not saved in mts files. In a game I am making I made item chests. When opened it drops items. It is an easy way to add chests to mts files. It works great for my game since I only want to give the player one or 2 items at a time. You can see what I did here.
Many of my mods are now a part of Minetest-mods. A place where you know they are maintained!

A list of my mods can be found here
 

afeys
Member
 
Posts: 17
Joined: Thu Mar 26, 2015 08:55

Re: Post your modding questions here

by afeys » Thu Oct 22, 2015 13:32

Ferk wrote:
afeys wrote:2/ Is there a way for a node to know if someone is stepping on it, or touching it? [...] minetest.register_on_playertouchnode or minetest.register_on_playersteponnode

This is exactly the same as what I was asking for in my last posts in this thread. It doesn't look like such a thing exists... I wish it got implemented, since I think a lot of people want it. The only workaround is to use an abm or a timer and check constantly for players.

I guess you are also making a dungeon mod?



sort of. My mod consists (or will consist if I ever get to finish it) of multiple types of buildings which are generated on the map. Amongst others a tower containing treasure chests defended by a hostile mob, a castle which gets randomly (sort of) generated by combining several pre-built building-part schematics to build either a small or a medium castle. The tower is nearly finished, but I wanted to add various traps, or blocks which decay if you step on them so you fall through if you stay in one place. But now you mention abm... maybe that is an option.... I will play around with it some more.
The mob part is something I also have to tackle. First I need to learn basic Blender, which seems like it has a very steep learning curve....
 

afeys
Member
 
Posts: 17
Joined: Thu Mar 26, 2015 08:55

Re: Post your modding questions here

by afeys » Thu Oct 22, 2015 13:41

@Don @Ferk

Thanks for the info.
I've now solved the chest problem: after placing the schematic in my world, I lookup all chests in the building and replace them by default:chest again. And then fill them with items (to fill them I use a piece of code I found in another mod: the villages mod by Sokomine I think).
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Thu Oct 22, 2015 13:59

That sounds like a cool mod.

blocks which decay if you step on them

The main problem with using ABMs to detect a player touching a node (other than being a lousy workaround for something that should be done in the engine) is that an ABM minimum interval is 1 second. So it's not very good for things that need a fast reaction since the player won't normally spend 1 second waiting in the node for the handler to kick in. But maybe for your usecase this would be fine. You might have to add an additional delay in case the player stepped the same instant the ABM activated, though.

a castle which gets randomly (sort of) generated by combining several pre-built building-part schematics to build either a small or a medium castle

That's very similar to what my subgame does. Maybe you can have a look at it, perhaps it helps. But most of dungeon_rooms is very specific to my usecase.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

afeys
Member
 
Posts: 17
Joined: Thu Mar 26, 2015 08:55

Re: Post your modding questions here

by afeys » Fri Oct 23, 2015 08:19

Ferk wrote:That's very similar to what my subgame does. Maybe you can have a look at it, perhaps it helps. But most of dungeon_rooms is very specific to my usecase.


Wow... just looked at your mod. looks very impressive.
 

User avatar
stu
Member
 
Posts: 737
Joined: Sat Feb 02, 2013 02:51
GitHub: stujones11

Re: Post your modding questions here

by stu » Fri Oct 23, 2015 18:32

Ferk wrote:The main problem with using ABMs to detect a player touching a node (other than being a lousy workaround for something that should be done in the engine) is that an ABM minimum interval is 1 second. So it's not very good for things that need a fast reaction since the player won't normally spend 1 second waiting in the node for the handler to kick in. But maybe for your usecase this would be fine. You might have to add an additional delay in case the player stepped the same instant the ABM activated, though


I doubt very much that stepping on/touching nodes will ever be handled by the engine, it would add way too much overhead, although I could be wrong there.

I suggest you take a look at how the mesecons pressure plates or player detectors work as those are reasonably responsive and iirc they do not rely on ABMs
 

User avatar
Napiophelios
Member
 
Posts: 752
Joined: Mon Jul 07, 2014 01:14
GitHub: Napiophelios
IRC: Nappi
In-game: Nappi

Re: Post your modding questions here

by Napiophelios » Fri Oct 23, 2015 19:05

Ferk wrote:That sounds like a cool mod.

blocks which decay if you step on them

The main problem with using ABMs to detect a player touching a node (other than being a lousy workaround for something that should be done in the engine) is that an ABM minimum interval is 1 second. So it's not very good for things that need a fast reaction since the player won't normally spend 1 second waiting in the node for the handler to kick in. But maybe for your usecase this would be fine. You might have to add an additional delay in case the player stepped the same instant the ABM activated, though.


Pyramids by BlockMen uses similar traps.

But Maze by Echo uses "close stones" that seem much faster to react to players position and spring the traps.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local maze_closer = {} -- list of all closer stones

-- closer stone definition
minetest.register_node("maze:closer", {
   tile_images = {"default_cobble.png"},
   inventory_image = minetest.inventorycube("default_cobble.png"),
   dug_item = '',
   material = { diggability = "not"},
   description = "Closestone",
})

-- detect player walk over closer stone (abm isn't fast enough)
minetest.register_globalstep(function(dtime)
   local players  = minetest.get_connected_players()
   for i,player in ipairs(players) do
      -- print(i.." "..player:get_player_name())
      for i, pos in ipairs(maze_closer) do
         local player_pos = player:getpos()
         local dist = math.sqrt( ((pos.x - player_pos.x) * (pos.x - player_pos.x)) +  ((pos.y - (player_pos.y - 0.5)) * (pos.y - (player_pos.y - 0.5))) +  ((pos.z - player_pos.z) * (pos.z - player_pos.z)) )
         if dist<3 then -- 2.2 would be enough, just make sure
            local meta = minetest.env:get_meta(pos)
            if dist<0.5 then
               meta:set_string("trap", "triggered")
            elseif dist > 1 then -- 0.71 would be enough, at least one node away
               if meta:get_string("trap") == "triggered" then
                  meta:set_string("trap", "")
                  minetest.env:add_node(pos,{name="default:cobble"})
                  minetest.env:add_node({x = pos.x, y = pos.y + 1, z = pos.z},{name="default:cobble"})
                  minetest.env:add_node({x = pos.x, y = pos.y + 2, z = pos.z},{name="default:cobble"})
               end
            end
         end
      end
   end

end)

-- create list of all closer stones (walk over detection now in globalstep, because abm isn't called often enough
minetest.register_abm(
   {nodenames = {"maze:closer"},
   interval = 1,
   chance = 1,
   action = function(pos, node, active_object_count, active_object_count_wider)
      local found = false
      for i, closer_pos in ipairs(maze_closer) do
         if closer_pos.x == pos.x and closer_pos.y == pos.y and closer_pos.z == pos.z then
            found = true
         end
      end
      if not found then
         table.insert(maze_closer, pos)
      end
   end,
})
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Fri Oct 23, 2015 19:36

It's faster because it uses globalstep. But that's also very hacky, and it doesn't look like he ever removes the node from the maze_closer table.. and you still have both an ABM and a globalstep handler running.

globalstep gets called every I think 0.05 seconds or something, if you don't keep track of the dtime (which it doesn't look like that code does) you are killing the CPU with that. Please correct me if I'm wrong.

If you don't have too many nodes to check it's probably more efficient to use timers, I guess timers get unloaded by the engine and handled more efficiently since the logic is all coded in C++. Note however that timers also won't get saved in mts schematics.

And all these approaches are workarounds, I still think it would be way better to have a handler on collision from the engine.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Fri Oct 23, 2015 19:50

stu wrote:I doubt very much that stepping on/touching nodes will ever be handled by the engine, it would add way too much overhead, although I could be wrong there.

Doesn't the engine already handle that? I mean.. how does it know a player can't go forward if there's a wall in front? or how does it know you are touching fire and should get damaged? I guess the server checks for collisions.
Or do you mean that that's client side? Even the damage_per_second?

Perhaps the problem is that the lua api is on a different, higher, level. Maybe some structural problem doesn't let them expose the collision logic to lua or they can't access the node definitions table. But I don't think the problem is overhead for checking the collisions.

stu wrote:I suggest you take a look at how the mesecons pressure plates or player detectors work as those are reasonably responsive and iirc they do not rely on ABMs

I had already done that, they use timers. Just a different way to apply the same approach used with ABMs. It's doable, just not very efficient.

afeys wrote:Wow... just looked at your mod. looks very impressive.

Thank you! :)
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

User avatar
Don
Member
 
Posts: 1641
Joined: Sat May 17, 2014 18:40
GitHub: DonBatman
IRC: Batman
In-game: Batman

Re: Post your modding questions here

by Don » Fri Oct 23, 2015 20:06

Doesn't the engine already handle that? I mean.. how does it know a player can't go forward if there's a wall in front? or how does it know you are touching fire and should get damaged? I guess the server checks for collisions.
Or do you mean that that's client side? Even the damage_per_second?

I believe you are referring to collision.cpp.
Many of my mods are now a part of Minetest-mods. A place where you know they are maintained!

A list of my mods can be found here
 

User avatar
Ben
Member
 
Posts: 157
Joined: Tue Mar 31, 2015 20:09

Re: Post your modding questions here

by Ben » Fri Oct 23, 2015 20:09

Ferk wrote:It's faster because it uses globalstep. But that's also very hacky, and it doesn't look like he ever removes the node from the maze_closer table.. and you still have both an ABM and a globalstep handler running.

I'm guessing you could use an on_destruct handler (or whatever it's called) to remove nodes from maze_closer. Other than that, you'd never want to remove nodes from that table – it's supposed to be all the closers in the world. For that use case, though, the ABM is much too agressive. Every few seconds, with less than certain probability, should get you just as far.

I've done that in a mod, but I also had to make sure the surrounding nodes around my special node were still there. Otherwise, nowadays, I'd try handling on_place and on_destroy, and saving the maze_closer table to disk.

Ferk wrote:globalstep gets called every I think 0.05 seconds or something, if you don't keep track of the dtime (which it doesn't look like that code does) you are killing the CPU with that. Please correct me if I'm wrong.

Wasn't it every 0.1 seconds? And in my experience, CPU is "free" nowadays. Or at least you should profile first, optimize later. I once found that a loop I was worried over took about 100 microseconds, and stopped worrying ;-)

(One tip to save CPU time: don't compare the distance to a threshold, compare the square of the distance to the square of the threshold. Saves you a math.sqrt call. But then agan, free nowadays.)

(Another tip: don't use maze_closer as a list and then iterate with ipairs to find a node with a given position, use it as a map / directory / hash and test against maze_closer["x.y.z"]. Use pairs if you do need to iterate. Yes, I understand it's someone else's code in this example, but this irked me, and I'd like to throw this out there.)

Ferk wrote:…And all these approaches are workarounds, I still think it would be way better to have a handler on collision from the engine.


For actual collisions as in "standing on" or "standing in", I've been iterating over all players and testing get_node() at the relevant positions. This probably won't work for "pushing against" or "standing near", but it seems to work. Or am I doing it wrong?
 

User avatar
Ferk
Member
 
Posts: 330
Joined: Tue Aug 18, 2015 17:18
GitHub: Ferk

Re: Post your modding questions here

by Ferk » Fri Oct 23, 2015 20:35

@Ben you are correct, it's 0.1
About the distance calculation, perhaps the best is to use vector.distance(p1, p2)

We have a very convenient API in Minetest for operating with vectors, it's a shame most mods don't use it.

For actual collisions as in "standing on" or "standing in", I've been iterating over all players and testing get_node() at the relevant positions. This probably won't work for "pushing against" or "standing near", but it seems to work. Or am I doing it wrong?

That's what I'm doing as well for a pacman mod I'm working on. Seems to work fine for collecting the pellets. The only problem is that sometimes there are rounding issues and some pellets were getting missed so I actually have to check 2 positions instead of 1. I tried minetest.find_node_near but I have to either do a get_node anyway or do it a second time for the other type of "touchable" nodes, so I decided against it. Also even radius 1 was too big, probably get_node is faster.

in my experience, CPU is "free" nowadays

My i7 processor roars like a tiger when playing pacman. In singleplayer. I have yet to test it on a server.
Last edited by Ferk on Fri Oct 23, 2015 20:51, edited 1 time in total.
{ ☠ Dungeontest ☠ , ᗧ••myarcade•• }
 

PreviousNext

Return to Modding Discussion

Who is online

Users browsing this forum: No registered users and 14 guests