minetest-mods / streets

Urban roadbuilding for Minetest! A collaborative mod by webD97, cheapie and Thomas-S
Other
22 stars 17 forks source link

Roads API #102

Open webD97 opened 6 years ago

webD97 commented 6 years ago

(This is still WIP, details following within the next days)

streets.roads.register_surface(name, surface_definition)

This will put the definition into a local table

streets.roads.register_label(name, label_definition)

This will put the definition into a local table

To allow for other mods (and therefore our own submods) to register their own surfaces and labels, this code only puts the definition into the private tables. They will be registered in a minetest.after(0, function) function to make sure that all other code has already been run, so that all definitions are there.

streets.roads.register_registration_hook(function)

Additionally, there should be streets.roads.register_registration_hook(function) function to allow other mods and submods to execute custom code during the registration of a road node. This could be used by #101 to register stairs.

Thomas--S commented 6 years ago

I've not read this in detail yet, but after skimming this, it seems to look good.

One little problem: You can't register anything in minetest.after(). This is a limitation of the Minetest engine. I suggest to run minetest.register_node() directly inside the streets.roads.register_label() function.

webD97 commented 6 years ago

Ah, so this is still not possible? I always thought minetest.after(0, function) would be run before the first server step, but it seems like it's running on the first server step. I'll need to think of something different then. It's not possible to register the node directly within register_label() because this would mean that surfaces registered after this will be ignored.

Thomas--S commented 6 years ago

As far as I can see, surfaces can only be different colors of asphalt.

Maybe we then could avoid the register_surface() by controlling the available asphalt colors ( = different surfaces) with a setting.

I know, this is not very elegant, but it would be a simple and light-weight approach.

webD97 commented 6 years ago

We would still need a way to the the API which nodes are "base nodes" for markings though.

Thomas--S commented 6 years ago

We could do this with three simple settings:

The lines above are no final suggestions, they should only show the concept.

webD97 commented 6 years ago

What I meant was: How do we tell the API which nodes to put the labels on? I really don't want to hardcode this...

Thomas--S commented 6 years ago

I fear the only possible way would be hardcoding. As far as I can see, only customization with settings would be technically possible.

I would prefer a register_surface() function, too, but I don't think this is possible.

webD97 commented 6 years ago

I'm sure there is a way. Nothing's impossible ;) I'll think about it this weekend.

Thomas--S commented 6 years ago

I think I found a possible solution.

I'll code it today to see if it works as expected.

Thomas--S commented 6 years ago

What do you think about this code? (untested)

streets.roads = {}

streets.roads.registered_labels = {}

streets.roads.registered_surfaces = {}

local register_combination = function(label_name, label_def, surface_name, surface_def)
    -- register nodes
end

streets.roads.register_surface = function(name, def)
    streets.roads.registered_surfaces[name] = def
    for label_name, label_def in streets.roads.registered_labels do
        register_combination(label_name, label_def, name, def)
    end
end

streets.roads.register_label = function(name, def)
    streets.roads.registered_labels[name] = def
    for surface_name, surface_def in streets.roads.registered_surfaces do
        register_combination(name, def, surface_name, surface_def)
    end
end
Thomas--S commented 6 years ago

I made a new suggestion for the roads API based on your suggestion and the signs API in 1eccfa06fa385dfca8dddbd7e27bdbed874b3259.

Quote from api.md:

Road Markings

streets.roads.register_label_collection()

streets.roads.register_label_collection({
    name = "sidelines",
    description = "Sidelines",
})

Registered collections are stored in streets.roads.registered_label_collections. streets.roads.registered_label_collections is structured as follows:

streets.roads.registered_collections = {
    ["sidelines"] = {
        name = "sidelines",
        description = "Sidelines",
    }
}

streets.roads.registered_label_collections must not be accessed directly. Use streets.roads.get_label_collection_definition(name) instead, which returns a copy of the definition or nil. name is the unique name of the collection, whose definition you want to get.

streets.roads.register_label()

streets.roads.register_label({
    name = "solid",
    description = "Solid Sideline",
    belongs_to = "sidelines",
})

To avoid confusions use <collection name>:<label name> when referring to labels.

Registered labels are stored in streets.roads.registered_labels. streets.roads.registered_labels is structured as follows:

streets.roads.registered_labels = {
    ["sidelines:solid"] = {
        name = "solid",
        description = "Solid Sideline",
        belongs_to = "sidelines",
    }
}

streets.roads.registered_labels must not be accessed directly. Use streets.roads.get_label_definition(name) instead, which returns a copy of the definition or nil. name is the unique name of the label, whose definition you want to get. It must have the format <collection name>:<label name>.

You can get a table of label definitions with streets.signs.get_label_definitions_by_collection(<collection name>).

Road Surface

streets.roads.register_surface()

streets.roads.register_surface({
    name = "asphalt",
    description = "Asphalt",
})

Registered surfaces are stored in streets.roads.registered_surfaces. streets.roads.registered_surfaces is structured as follows:

streets.roads.registered_surfaces = {
    ["asphalt"] = {
        name = "asphalt",
        description = "Asphalt",
    }
}

streets.roads.registered_surfaces must not be accessed directly. Use streets.roads.get_surface_definition(name) instead, which returns a copy of the definition or nil. name is the unique name of the surface, whose definition you want to get.


I'm looking forward to your comments.