Make the API less rigid.
-
- Filter Inserter
- Posts: 952
- Joined: Sat May 23, 2015 12:10 pm
- Contact:
Make the API less rigid.
In the current system the API is extremely rigid in what you are allowed to do.
You can't create a power generator without hacking a hidden boiler to magically get heated water. You can't create a lamp without having to give it power.
You can't read circuit input without a hack to binary search each signal separately. You can't output to a circuit without creating an invisible constant combinator. You can't create a filtered generic inventory.
Give modders enough modules that they can mix and match everything.
As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
You can't create a power generator without hacking a hidden boiler to magically get heated water. You can't create a lamp without having to give it power.
You can't read circuit input without a hack to binary search each signal separately. You can't output to a circuit without creating an invisible constant combinator. You can't create a filtered generic inventory.
Give modders enough modules that they can mix and match everything.
As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
Re: Make the API less rigid.
Already planned for 0.13.ratchetfreak wrote:You can't create a power generator without hacking a hidden boiler to magically get heated water.
...
You can't create a lamp without having to give it power.
Ready and waiting in 0.12.5.ratchetfreak wrote:You can't read circuit input without a hack to binary search each signal separately.
This is how the circuit network works - in order to output a signal into a given network you need an entity connected to that network.ratchetfreak wrote:You can't output to a circuit without creating an invisible constant combinator.
I'll see what Kovarex has to say about adding support for this.ratchetfreak wrote:You can't create a filtered generic inventory.
I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.oratchetfreak wrote:Give modders enough modules that they can mix and match everything.
As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.
If you want to get ahold of me I'm almost always on Discord.
-
- Filter Inserter
- Posts: 952
- Joined: Sat May 23, 2015 12:10 pm
- Contact:
Re: Make the API less rigid.
greatRseding91 wrote:Already planned for 0.13.ratchetfreak wrote:You can't create a power generator without hacking a hidden boiler to magically get heated water.
...
You can't create a lamp without having to give it power.
Ready and waiting in 0.12.5.ratchetfreak wrote:You can't read circuit input without a hack to binary search each signal separately.
but you are limited to 15 signals (last I checked) and you need to power it.Rseding91 wrote:This is how the circuit network works - in order to output a signal into a given network you need an entity connected to that network.ratchetfreak wrote:You can't output to a circuit without creating an invisible constant combinator.
Rseding91 wrote:I'll see what Kovarex has to say about adding support for this.ratchetfreak wrote:You can't create a filtered generic inventory.
I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.oratchetfreak wrote:Give modders enough modules that they can mix and match everything.
As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.
I meant make it more component based.
Like for an assembler lvl3 you have 3 inventories; a filtered input (based on the recipe), a output and module slots. (Additionally a liquid connection for blue belts and such)
It also has a power consumer with buffer and a gui that shows the state of it all and an animation.
A boiler has a power producer and a liquid connection.
A capacitor has a power consumer and a power producer.
Let modders mix and match those components.
Re: Make the API less rigid.
Not really a contradiction. He wants the api to have the lower-level interface used to make the vanilla items, instead of a limited ability to tweak the vanilla end products. Hypothetical example, a "crafting-machine" prototype that could be extended by a mod to make any of the vanilla crafting machines - or any number of original machines combining aspects of those with novel functionality.Rseding91 wrote:I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.oratchetfreak wrote: As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
This I grant is an entirely valid response. It's possible to do this sort of thing in c++, but the language wasn't designed for it, and the implementation details of trying to apply a pattern like mixins in c++ can get very nasty very quickly. So, giving any prototypes the potential to become "all the things" is an unrealistic request. That said, generic prototypes for families where underlying abstract base classes exist (probably - I can only guess here), like crafting machines (which share fundamentals like recipes, progress, etc, and so I'm betting derive from a common abstract class) could be extended into prototypeable non-abstract, but by themselves perhaps non-functional, classes that could be fully defined and implemented by mods. They would, obviously, result in machines that were less efficient than those hard-coded in c++, or derived from those by only a few property changes in lua, but they would be correspondingly more flexible and allow things that would be impossible, or unnecessarily convoluted, currently.Rseding91 wrote: Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.
My Mods:
Nixie Tubes - numeric displays for your circuit networks!
Logistic Combinators - use logistics values in circuit logic! -
Autowire - automate red/green wire connections
Nixie Tubes - numeric displays for your circuit networks!
Logistic Combinators - use logistics values in circuit logic! -
Autowire - automate red/green wire connections
-
- Filter Inserter
- Posts: 952
- Joined: Sat May 23, 2015 12:10 pm
- Contact:
Re: Make the API less rigid.
exactlyGopherAtl wrote:Not really a contradiction. He wants the api to have the lower-level interface used to make the vanilla items, instead of a limited ability to tweak the vanilla end products. Hypothetical example, a "crafting-machine" prototype that could be extended by a mod to make any of the vanilla crafting machines - or any number of original machines combining aspects of those with novel functionality.Rseding91 wrote:I don't understand this - you want to be able to emulate existing stuff but without copying existing stuff. The statement contradicts its self O.oratchetfreak wrote: As a rule of thumb give modders enough information and utilities to fully emulate existing stuff without copying the built in entities.
With Pimpl (Pointer to IMPLementation) it's less of a hassle (and customizable at runtime) though at the cost of a layer of indirection.GopherAtl wrote:This I grant is an entirely valid response. It's possible to do this sort of thing in c++, but the language wasn't designed for it, and the implementation details of trying to apply a pattern like mixins in c++ can get very nasty very quickly. So, giving any prototypes the potential to become "all the things" is an unrealistic request. That said, generic prototypes for families where underlying abstract base classes exist (probably - I can only guess here), like crafting machines (which share fundamentals like recipes, progress, etc, and so I'm betting derive from a common abstract class) could be extended into prototypeable non-abstract, but by themselves perhaps non-functional, classes that could be fully defined and implemented by mods. They would, obviously, result in machines that were less efficient than those hard-coded in c++, or derived from those by only a few property changes in lua, but they would be correspondingly more flexible and allow things that would be impossible, or unnecessarily convoluted, currently.Rseding91 wrote: Object oriented C++ doesn't lend its self well to "mix and match any random piece of the code into one entity" - each entity supports the given coded behaviors and properties. Without re-writing the entity you can't just make it do something else.
So each component has a implementation of the generic base it uses. A electric power module would connect to the nearby networks to fill its internal buffer and as the entity needs power it will pull it from its buffer (or from network directly). A infinite power module would have an infinitely full buffer. A burner power module would consume the fuel in the connected fuel inventory as needed. A solar module would only have power when the sun is out.
Re: Make the API less rigid.
All of this is assuming a class structure that, from what rseding has said, just doesn't exist in the code base right now, though, and it also supposes a base class common to everything that has at least the rudimentary interface for every possible feature. By the sound of it the actual code is using a more traditional hierarchical inheritance model; changing that at this stage would be pretty major.ratchetfreak wrote: With Pimpl (Pointer to IMPLementation) it's less of a hassle (and customizable at runtime) though at the cost of a layer of indirection.
So each component has a implementation of the generic base it uses. A electric power module would connect to the nearby networks to fill its internal buffer and as the entity needs power it will pull it from its buffer (or from network directly). A infinite power module would have an infinitely full buffer. A burner power module would consume the fuel in the connected fuel inventory as needed. A solar module would only have power when the sun is out.
My Mods:
Nixie Tubes - numeric displays for your circuit networks!
Logistic Combinators - use logistics values in circuit logic! -
Autowire - automate red/green wire connections
Nixie Tubes - numeric displays for your circuit networks!
Logistic Combinators - use logistics values in circuit logic! -
Autowire - automate red/green wire connections
-
- Filter Inserter
- Posts: 952
- Joined: Sat May 23, 2015 12:10 pm
- Contact:
Re: Make the API less rigid.
Looking at how the API works (and what help() returns) I wouldn't be surprised if there was a abstract Entity class that binds all the entities together.
All that's really needed on the engine side is letting each module act. Each would have a physical representation (bounding box for connecting with the power grid, or letting inserters interact with the inventory, a point where the circuit network will attach to etc.)
And then let the mod interact with the owner entity and query the modules it installed
All that's really needed on the engine side is letting each module act. Each would have a physical representation (bounding box for connecting with the power grid, or letting inserters interact with the inventory, a point where the circuit network will attach to etc.)
And then let the mod interact with the owner entity and query the modules it installed
Re: Make the API less rigid.
I agree with the sort of general plea from the title, if not all the specific examples. I've noticed a lot of the time, the string in the prototype "type" field enables or disables "magic" properties. Turrets have to be of type "ammo turret" or else whatever code the game has for the turret AI does not execute. So there is this whole complex turret aiming / inventory system that is hidden from entities and only turned on if you set the type field to "ammo turret". This is the same sort of problem with logistics containers, you have to set their type to "logistics containers" or else your container is not part of the logistics system. Shouldn't there be a property to set the logistics type? Not a hard-coded type? Hardcoding these types makes it very difficult to mix and match two types together.
Re: Make the API less rigid.
When you define the type in the Lua prototype you're telling the game engine which C++ class of the entity to use. Each class has code for that given entity type and it's behaviors.Afforess wrote:I agree with the sort of general plea from the title, if not all the specific examples. I've noticed a lot of the time, the string in the prototype "type" field enables or disables "magic" properties. Turrets have to be of type "ammo turret" or else whatever code the game has for the turret AI does not execute. So there is this whole complex turret aiming / inventory system that is hidden from entities and only turned on if you set the type field to "ammo turret". This is the same sort of problem with logistics containers, you have to set their type to "logistics containers" or else your container is not part of the logistics system. Shouldn't there be a property to set the logistics type? Not a hard-coded type? Hardcoding these types makes it very difficult to mix and match two types together.
Nothing is "hidden" from other entity types they simply aren't coded to run with that logic.
A real world example:
"Cars" all do the same basic concept: drive. Most have 4 wheels and an engine. However, a minivan and a pickup truck have completely different internal components and you can't just "switch the engines" on them without massive structural changes to both cars. The same can be said about Factorio entities.
Regarding the "hard coded" comment: the way you set the chest to the logistic type is by defining the /type/ property in the prototype to that of the logistic-container.
If you want to get ahold of me I'm almost always on Discord.
Re: Make the API less rigid.
Exactly. That is the very definition of hidden behavior.Rseding91 wrote:When you define the type in the Lua prototype you're telling the game engine which C++ class of the entity to use. Each class has code for that given entity type and it's behaviors.Afforess wrote:I agree with the sort of general plea from the title, if not all the specific examples. I've noticed a lot of the time, the string in the prototype "type" field enables or disables "magic" properties. Turrets have to be of type "ammo turret" or else whatever code the game has for the turret AI does not execute. So there is this whole complex turret aiming / inventory system that is hidden from entities and only turned on if you set the type field to "ammo turret". This is the same sort of problem with logistics containers, you have to set their type to "logistics containers" or else your container is not part of the logistics system. Shouldn't there be a property to set the logistics type? Not a hard-coded type? Hardcoding these types makes it very difficult to mix and match two types together.
Nothing is "hidden" from other entity types they simply aren't coded to run with that logic.
Er, that is exactly my complaint. Types should be defined by their own set of fields. If I want a car, I should have a prototype for a "car" that defines what a "car" is (has 4 wheels, moves, consumes fuel, can contain 1 passenger, etc). Right now, you specify a magic word (ex: type = "car") and your prototype is a car.Rseding91 wrote: Regarding the "hard coded" comment: the way you set the chest to the logistic type is by defining the /type/ property in the prototype to that of the logistic-container.
HOWEVER, I realize this is not going to happen. It is a huge change, and at this late stage, not worth it. It would be nice if the predefined magic types were a bit more flexible.
Re: Make the API less rigid.
That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).Afforess wrote:Er, that is exactly my complaint. Types should be defined by their own set of fields. If I want a car, I should have a prototype for a "car" that defines what a "car" is (has 4 wheels, moves, consumes fuel, can contain 1 passenger, etc). Right now, you specify a magic word (ex: type = "car") and your prototype is a car.Rseding91 wrote: Regarding the "hard coded" comment: the way you set the chest to the logistic type is by defining the /type/ property in the prototype to that of the logistic-container.
HOWEVER, I realize this is not going to happen. It is a huge change, and at this late stage, not worth it. It would be nice if the predefined magic types were a bit more flexible.
Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
If you want to get ahold of me I'm almost always on Discord.
-
- Filter Inserter
- Posts: 952
- Joined: Sat May 23, 2015 12:10 pm
- Contact:
Re: Make the API less rigid.
ever heard of dependency injection?Rseding91 wrote: That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).
Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
There an object has a set of fields and on construction those fields get filled with objects depending on config/"circumstances".
Re: Make the API less rigid.
Basically this, yes. There are plenty of game engines & games that do similar things. See modding in Civilization 5 (XML / Lua based as well).ratchetfreak wrote:ever heard of dependency injection?Rseding91 wrote: That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).
Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
There an object has a set of fields and on construction those fields get filled with objects depending on config/"circumstances".
I will agree that if you don't plan the initial design this way, it is far too much effort to change later... As it is already too late, this debate is moot.
Re: Make the API less rigid.
I don't think that means what you think it means: https://en.wikipedia.org/wiki/Dependency_injection - that's basically how Factorio operates: prototypes define the instance properties and the game engine creates the corresponding entity with those instance properties.ratchetfreak wrote:ever heard of dependency injection?Rseding91 wrote: That's just not how any of this works in real-world programming. I don't know of one game or game engine that works the way you're talking about. In fact I'm not even sure a game could be implemented to work that way (since no one has done it on a game that has actually sold).
Even if it was feasible to implement the performance implications of making it work and the resulting code would be un-maintainable :\
There an object has a set of fields and on construction those fields get filled with objects depending on config/"circumstances".
If you want to get ahold of me I'm almost always on Discord.
-
- Filter Inserter
- Posts: 952
- Joined: Sat May 23, 2015 12:10 pm
- Contact:
Re: Make the API less rigid.
Then give us more control over what those injected instance properties are.Rseding91 wrote:
I don't think that means what you think it means: https://en.wikipedia.org/wiki/Dependency_injection - that's basically how Factorio operates: prototypes define the instance properties and the game engine creates the corresponding entity with those instance properties.
Here's a challenge: each time you create a new entity type, first go on the modders side of the API and try to implement it. If you can't or you have to do it in a convoluted way then add the needed functionality to the modding API. After that you can hardcode the entity in the engine. Or take a look at the existing mods and see where they have to hack around the current API and go make life easier on them.
For example combinators, they need to read the input, do some math and write output. Writing output could be done by hiding a smart chest in there but that doesn't give access to the (new) special signals, the constant combinator is limited to a fixed number of signals. Reading the value needs a binary search on a hidden lamp.
GUI wise what's needed is a way to select an item/signal.
Re: Make the API less rigid.
Kerbal space program implemented a system called the part modules, which let any part, contain any number of modules, with each module having its own function.
Explanation on the KSP wiki
Im no expert or do i have much experience modding in KSP, but the part module does make it really simple to make custom parts, and picking and choosing what functions a specific part will have
Explanation on the KSP wiki
Im no expert or do i have much experience modding in KSP, but the part module does make it really simple to make custom parts, and picking and choosing what functions a specific part will have
Re: Make the API less rigid.
Alright, I was messing with trains and have found allot of stuff not in the lua API.
Good example: Electric trains that connect to the power network.
You can set the energy source to an electric consumer with no complaints, but it won't connect to anything.
The energy supply is reset on each tick. no value to access the buffer supply of energy, even for the burner source type (can't even access energy of assembly machines!).
Only way to make it work and connect to the electric network would be to put in an invisible accumulator that connects to the energy network, then EACH tick, pull 600 from it's buffer and put 1066.6 into the train so it can move at full power for a single tick. any more than 1066.6 will be lost! you also have to remove and place the invisible accumulator each tick if you want it to seem like the train gets power from the network.
Trains support running off of electric power but to get them to move, you have to hack allot per tick! no access to internal energy buffer!
And that's just for a lonely train.
Good example: Electric trains that connect to the power network.
You can set the energy source to an electric consumer with no complaints, but it won't connect to anything.
The energy supply is reset on each tick. no value to access the buffer supply of energy, even for the burner source type (can't even access energy of assembly machines!).
Only way to make it work and connect to the electric network would be to put in an invisible accumulator that connects to the energy network, then EACH tick, pull 600 from it's buffer and put 1066.6 into the train so it can move at full power for a single tick. any more than 1066.6 will be lost! you also have to remove and place the invisible accumulator each tick if you want it to seem like the train gets power from the network.
Trains support running off of electric power but to get them to move, you have to hack allot per tick! no access to internal energy buffer!
And that's just for a lonely train.
Will code for Food. I also have 11+ mods!
Re: Make the API less rigid.
You are accessing the internal energy buffer of the train every time you set entity.energy. If you couldn't se it then you can't access the buffer - but you can. You can also access the energy of an assembling machine using the default entity.energy.vzybilly wrote:Alright, I was messing with trains and have found allot of stuff not in the lua API.
Good example: Electric trains that connect to the power network.
You can set the energy source to an electric consumer with no complaints, but it won't connect to anything.
The energy supply is reset on each tick. no value to access the buffer supply of energy, even for the burner source type (can't even access energy of assembly machines!).
Only way to make it work and connect to the electric network would be to put in an invisible accumulator that connects to the energy network, then EACH tick, pull 600 from it's buffer and put 1066.6 into the train so it can move at full power for a single tick. any more than 1066.6 will be lost! you also have to remove and place the invisible accumulator each tick if you want it to seem like the train gets power from the network.
Trains support running off of electric power but to get them to move, you have to hack allot per tick! no access to internal energy buffer!
And that's just for a lonely train.
The actual issue is electric buffer sizes are dynamically set to the idle power usage of the entity and resized as the entity starts to draw more power. Trains are not designed to run off electricity - neither are trees - that's why they don't work when you set them to run off electricity.
Because trains (and trees and most entities) don't use electricity they don't run the code to use electricity and don't eat up un-necessary CPU time doing stuff that they would 99.99% of the time not use.
If you want to get ahold of me I'm almost always on Discord.
-
- Filter Inserter
- Posts: 952
- Joined: Sat May 23, 2015 12:10 pm
- Contact:
Re: Make the API less rigid.
But what he wants is to set the buffer size to some (higher) value and only refill once in a while instead of excess being lostRseding91 wrote:
You are accessing the internal energy buffer of the train every time you set entity.energy. If you couldn't se it then you can't access the buffer - but you can. You can also access the energy of an assembling machine using the default entity.energy.
The actual issue is electric buffer sizes are dynamically set to the idle power usage of the entity and resized as the entity starts to draw more power. Trains are not designed to run off electricity - neither are trees - that's why they don't work when you set them to run off electricity.
Because trains (and trees and most entities) don't use electricity they don't run the code to use electricity and don't eat up un-necessary CPU time doing stuff that they would 99.99% of the time not use.
Besides that getting explicit control over trains would also be nice like setting a manual path and telling it to go instead of pathing to a station.
Letting us create a new type of rail signal (path signal for example or a circuit controlled signal) would also be nice. (fully controlled by the mod code)
Re: Make the API less rigid.
the trains show in the gui how much of their buffer is filled with energy. when setting it to the max, the gui still shows empty. also, when the gui shows full, the train can go a long distance but when I set it, even to an insane amount, it only goes about a tile... or less.
that's why I say that it doesn't change the buffer of energy, because it's changing a "per tick buffer".
that's why I say that it doesn't change the buffer of energy, because it's changing a "per tick buffer".
Will code for Food. I also have 11+ mods!