Multiple requests
Posted: Thu Mar 10, 2016 10:17 pm
Hello everyone!
I am a new factorio player, got in on a steam release.
I am a programmer (as my job) and I have made two WOW addons (one popular one), so i am familiar with LUA, so I have decided to write a mod. I have got two ideas that sounds at least interesting (it may be or may be not, it is hard to say because both are major gameplay changes) and I have started implementing one of these.
I know the game is in an early access, so modding api is in alpha stage, that's why I am making this post as a feedback. That's some problems and annoyances I have encountered.
ItemStacks and SimpleItemStacks.
They are, well, simple, but it is a little bit of nightmare when you try to do some generic stuff that works with items. There are 6 methods in ItemStack to read/write blueprint contents (thats almost half!) and also few values for ammo/damage/durability, and also item grids and whatever comes in the future. And all these parameters are irretrievable when you use SimpleItemStacks
My suggestion is to make SimpleItemStack format like {name="", count=0, data={...}} where data can be something (type-related).
examples:
blueprints data = {icons={"item_1","item_2"},entities={...}}
ammo data = {ammo=0}
Of course, you cannott set_stack() with invalid data, but you can store and copy it without any knowledge what is inside
ItemStack methods like copy_to(target_item_stack), stack_to(target_inventory / entity), swap(with_item_stack), merge(target_item_stack) are all doable in lua but it would be convinient if you could do it easily without thinking about possible side effects (like stacking damaged items etc)
transport lines: get item count, get item position (by index), get ItemStack(by index). Item stack is valid this frame only.
Inventory features:
- shared inventories
This may look like it is something very specific but IMO this has a lot of usages. The idea is that you can call something like inventory.share_with(another_inventory) and these inventories will get same content and making changes on one of them changes another one. Very useful for fake (invisible) attached entities. This may be very hard or not so hard to implement depending on how inventories was actually implemented.
- an ability to perform a one-time copy to another inventory could also be useful when swapping entities
Entity features:
- replace entity command. Replace entity with another one while transfering all data to a new one. This works like fast-replace by player.
- hidden entities. Hidden entity doesn't collide with anything, it could be created hidden (to avoid collision checks on creation) and it could be shown/hidden with script. That is useful for temporary removing an entity while preserving its configuration.
Events
We need more events! In factorio, player initiates almost everything, so if we have had an event for each possible player action, we could have control on about everything!
- player drops an item
- player fastreplaces an entity
- player rotates an entity on cursor (funny fact: you can rotate an entity on player's cursor but you can neither get current rotation, nor detect when player rotates it, so it is kind of useless)
- player moves entity on cursor (bonus point if you can highlight this entity as red (non-placeable) for custom placing restrictions
- player interacts with an inventory (lots of actions - takes stack, puts a stack, shift-clicks a stack, etc - and also loots items (for example when destroying a container or changine recipe in assembling machine)
- player changes entity configuration (e.g. recipe or request slots)
- entity spawn (generic, also for scripted spawns) / destroy
Also we need a way to cancel events (at least that for player action), for example with calling event.cancel() or setting event.cancelled=true. Cancelled events don't apply.
Localize events
If we have lots of events that got dispatched frequently, this could cause lags with lots of addons doing like: "oh, something had happened! Oh, that's not my business", so it would be great if you can subscribe for specific events (specific entitiy spawn, etc)
suggested method surface.get_entity(position) - returns an entity at position (the same one as if you pointed a mouse pointer there) - single entity or nil - could be a lot better then scanning an area in many cases
Overall:
some methods should return nil instead of throwing errors. That's controversial and i know about pcall(), but sometimes it is not possible or not easy to know if some call would cause error or not. At least for read-only functions, sometimes nil would be better.
for example entity.get_inventory(). It is not possible to know how many inventories does an entity have for doing some generic stuff
also methods like entity.get_request_slot() - it is restricted to logistic-container (that's ok and can be checked) but not all of items with type 'logistic-container' has it (only requester chests, but how do you know if custom logistic container is a request chest?)
Lua has special article for "nil or error" http://www.lua.org/pil/8.3.html ("An exception that is easily avoided should raise an error; otherwise, it should return an error code.")
As for higher-level apis (interaction between entities, interaction with logistic robots, etc) - this is for distant future, but it should exist. Mods should be able to interact with each other (and with base mod) generically - for example custom inserter calls can_insert() for an entity he has no knowledge about, another mod overrides this function for that specific entity and performs custom checks, etc.
P.S. I got logged off while writing this and after relogging this text was lost... I had to perform browser process dump to retrieve this text.
I am a new factorio player, got in on a steam release.
I am a programmer (as my job) and I have made two WOW addons (one popular one), so i am familiar with LUA, so I have decided to write a mod. I have got two ideas that sounds at least interesting (it may be or may be not, it is hard to say because both are major gameplay changes) and I have started implementing one of these.
I know the game is in an early access, so modding api is in alpha stage, that's why I am making this post as a feedback. That's some problems and annoyances I have encountered.
ItemStacks and SimpleItemStacks.
They are, well, simple, but it is a little bit of nightmare when you try to do some generic stuff that works with items. There are 6 methods in ItemStack to read/write blueprint contents (thats almost half!) and also few values for ammo/damage/durability, and also item grids and whatever comes in the future. And all these parameters are irretrievable when you use SimpleItemStacks
My suggestion is to make SimpleItemStack format like {name="", count=0, data={...}} where data can be something (type-related).
examples:
blueprints data = {icons={"item_1","item_2"},entities={...}}
ammo data = {ammo=0}
Of course, you cannott set_stack() with invalid data, but you can store and copy it without any knowledge what is inside
ItemStack methods like copy_to(target_item_stack), stack_to(target_inventory / entity), swap(with_item_stack), merge(target_item_stack) are all doable in lua but it would be convinient if you could do it easily without thinking about possible side effects (like stacking damaged items etc)
transport lines: get item count, get item position (by index), get ItemStack(by index). Item stack is valid this frame only.
Inventory features:
- shared inventories
This may look like it is something very specific but IMO this has a lot of usages. The idea is that you can call something like inventory.share_with(another_inventory) and these inventories will get same content and making changes on one of them changes another one. Very useful for fake (invisible) attached entities. This may be very hard or not so hard to implement depending on how inventories was actually implemented.
- an ability to perform a one-time copy to another inventory could also be useful when swapping entities
Entity features:
- replace entity command. Replace entity with another one while transfering all data to a new one. This works like fast-replace by player.
- hidden entities. Hidden entity doesn't collide with anything, it could be created hidden (to avoid collision checks on creation) and it could be shown/hidden with script. That is useful for temporary removing an entity while preserving its configuration.
Events
We need more events! In factorio, player initiates almost everything, so if we have had an event for each possible player action, we could have control on about everything!
- player drops an item
- player fastreplaces an entity
- player rotates an entity on cursor (funny fact: you can rotate an entity on player's cursor but you can neither get current rotation, nor detect when player rotates it, so it is kind of useless)
- player moves entity on cursor (bonus point if you can highlight this entity as red (non-placeable) for custom placing restrictions
- player interacts with an inventory (lots of actions - takes stack, puts a stack, shift-clicks a stack, etc - and also loots items (for example when destroying a container or changine recipe in assembling machine)
- player changes entity configuration (e.g. recipe or request slots)
- entity spawn (generic, also for scripted spawns) / destroy
Also we need a way to cancel events (at least that for player action), for example with calling event.cancel() or setting event.cancelled=true. Cancelled events don't apply.
Localize events
If we have lots of events that got dispatched frequently, this could cause lags with lots of addons doing like: "oh, something had happened! Oh, that's not my business", so it would be great if you can subscribe for specific events (specific entitiy spawn, etc)
suggested method surface.get_entity(position) - returns an entity at position (the same one as if you pointed a mouse pointer there) - single entity or nil - could be a lot better then scanning an area in many cases
Overall:
some methods should return nil instead of throwing errors. That's controversial and i know about pcall(), but sometimes it is not possible or not easy to know if some call would cause error or not. At least for read-only functions, sometimes nil would be better.
for example entity.get_inventory(). It is not possible to know how many inventories does an entity have for doing some generic stuff
also methods like entity.get_request_slot() - it is restricted to logistic-container (that's ok and can be checked) but not all of items with type 'logistic-container' has it (only requester chests, but how do you know if custom logistic container is a request chest?)
Lua has special article for "nil or error" http://www.lua.org/pil/8.3.html ("An exception that is easily avoided should raise an error; otherwise, it should return an error code.")
As for higher-level apis (interaction between entities, interaction with logistic robots, etc) - this is for distant future, but it should exist. Mods should be able to interact with each other (and with base mod) generically - for example custom inserter calls can_insert() for an entity he has no knowledge about, another mod overrides this function for that specific entity and performs custom checks, etc.
P.S. I got logged off while writing this and after relogging this text was lost... I had to perform browser process dump to retrieve this text.