Skip to content

Commit 260d9c4

Browse files
authored
Merge pull request #328 from ParadoxiKat/HeatPipes
Heat pipes
2 parents 84da1be + 1397568 commit 260d9c4

7 files changed

Lines changed: 523 additions & 335 deletions

File tree

devdocs/contracting.md

Lines changed: 6 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -22,210 +22,15 @@ Note that it is a year old, and only 75% or so accurate.
2222

2323
- Onboarding and global variable audit (40 h)
2424
- fa-info preparation for 2.0, aka `]` key (17 h, 57h total).
25-
- Refactor cursor handling to a new viewpoint module to allow for space age and remote view enhancements (15h give or
26-
take a bit, total 75 h).
25+
- Refactor cursor handling to a new viewpoint module to allow for space age and remote view enhancements (~20h give or
26+
take a bit, total ~78 h).
27+
- Input Refactor for 2.0 (~52h, total 131h)
28+
- Test Larger Cursors on Gleba. Tested; no issues found. (~1h, total 132h)
29+
- Aquilo iceberg scanner and new terrain category (11h, total 143H)
30+
- Heat Pipes read like fluid network (22H total 165)
2731

2832
# Tasks
2933

30-
## Input Cleanup
31-
32-
Issue: tons, not going to bother. Blocks a lot.
33-
34-
### Background and Motivation
35-
36-
Factorio represents custom inputs with `CustomInputPrototype`. For example (from our mod):
37-
38-
```
39-
{
40-
type = "custom-input",
41-
name = "click-menu",
42-
key_sequence = "LEFTBRACKET",
43-
consuming = "none",
44-
},
45-
```
46-
47-
Which means "When leftbracket is pressed, find an event handler named click-menu and call it".
48-
49-
These are in data.lua, and run as part of the "data lifecycle". but there's a couple problems.
50-
51-
First is the small problem that data.lua is huge. We're here so we can fix that while we do the rest (it can be split).
52-
53-
But the real motivating problem: Factorio allows inputs to conflict. When this happens, all events for all related keys
54-
will trigger in some arbitrary but deterministic order. In the ancient past, the mod decided this was the way to handle
55-
"overloading" a key, e.g. all the different things `[` might do each get their own prototype.
56-
57-
Now, in order to add new functionality, one must make sure that all of the conditions line up so that it is not possible
58-
for any conflicting event handlers to run. This is a potentially significant radius, because for example `[` is used to
59-
build, drive blueprints, run menus, manage inventories...and each of these may or may not be in an event by itself. On
60-
top of that there are event stateful changes where keys temporarily mean something else. This can no longer be reasoned
61-
about. As a result, it's not possible to clean up, centralize, or add new menus, or continue to "overload" keys. It
62-
may seem like overloading keys is a bad idea in the first place, but truthfully we are out of keys as it is.
63-
64-
What we give up (at least temporarily) is the ability for users to map individual actions to other keys. We can bring
65-
that back with alternate prototypes which are not mapped to any keys by default, but only if there is enough demand. It
66-
is suspected that no one really remaps anything.
67-
68-
### The Work/Plan
69-
70-
We have code like this:
71-
72-
```
73-
script.on_event("click-menu", function(event)
74-
local pindex = event.player_index
75-
local router = UiRouter.get_router(pindex)
76-
77-
if not check_for_player(pindex) then return end
78-
if players[pindex].last_click_tick == event.tick then return end
79-
local p = game.get_player(pindex)
80-
81-
if router:is_ui_open() then
82-
-- stuff
83-
end
84-
end)
85-
```
86-
87-
Where the condition is whether or not it should do anything at all, sandwiched inside an if statement. Or, code like
88-
this:
89-
90-
```
91-
---@param event EventData.CustomInputEvent
92-
script.on_event("vanilla-toggle-personal-logistics-info", function(event)
93-
local pindex = event.player_index
94-
local p = game.get_player(pindex)
95-
local c = p.character
96-
if not c then return end
97-
98-
local p = c.get_logistic_point(defines.logistic_member_index.character_requester)
99-
if not p then return end
100-
101-
-- Ok we can do it.
102-
end)
103-
```
104-
105-
Where the conditions return early if there is nothing to be done. My preference is for the latter pattern because it
106-
avoids the indent "waterfall". But in any case, the problem here is that these are in event handlers by themselves.
107-
108-
What we want to do is get off the fun names to systemic names, and then collapse these. The proposed scheme is
109-
`fa-[cas]-key` for example `fa-c-leftbracket` is ctrl + leftbracket, `fa-j` is just j, etc. The cas are "bitflags" and
110-
always specified in that order (none for no modifiers, `c` is control, `a` alt, `s` shift). A single prototype per key
111-
combo covers all others that were on the key, so we drop those. Then we can perform a mostly mechanical transformation,
112-
just far enough out that the AI can't quite do it:
113-
114-
```
115-
script.on_event("old1", function(event)
116-
if condition1 then
117-
-- do it
118-
end
119-
end)
120-
121-
122-
script.on_event("old2", function(event)
123-
if condition2 then
124-
-- Do it
125-
end
126-
end)
127-
```
128-
129-
Would become:
130-
131-
```
132-
local function kb_old1(event)
133-
-- Code without the condition
134-
end
135-
136-
local function kb_old2(event)
137-
-- Code without the condition
138-
end
139-
140-
script.on_event("fa-newkey", function(event)
141-
if condition1 then kb_old1(event)
142-
elseif condition2 then kb_old2(event) end
143-
-- If we fall off the end that's fine to do nothing.
144-
end)
145-
```
146-
147-
Which ensures that only one of them runs per press. the `kb_` prefix is kind of literal, just to let us know "this is a
148-
block of code from the keyboard", and indeed for smaller ones (e.g which already call out to a module) not having the
149-
intermediate function is fine. You will want to pass the event around for now rather than deconstructing at the top,
150-
and annotate:
151-
152-
```
153-
---@param event EventData.CustomInputEvent
154-
```
155-
156-
Note the following:
157-
158-
- We genuinely don't know the old order. Bias UI/menu conditions toward the top but other than that it's ambiguous and
159-
we don't care right now because getting this far will let us see if that ever matters, since overlapping/wrong-order
160-
conditions won't both trigger anyhmore.
161-
- Control.lua has a ton of code duplication. For now that's out of scope, because most of it is being moved to modules
162-
and doing so was blocked by input being a problem. For instance the menu_up/menu_left/etc. functions are very clearly
163-
*almost* but not quite duplicates that could be "fixed", except new UI framework wants to just plug in.
164-
- That said, don't add more if it's easy to avoid. If it's not easy to avoid, shrug.
165-
- testing is a pain. It's fine to break stuff. The only real test is "play a full run of the game". So do your best
166-
but don't freak out over that, no judgement as long as like really basic stuff works.
167-
- Lua function order matters. Callees must be declared before callers when using the `local function` syntax.
168-
- Feel free to be rid of any obvious dead code.
169-
- Feel free to mark things which are local to control.lua as locals if you find any, though going after them is out of
170-
scope; it's a self-resolving problem down the road.
171-
- linked_game_control and consuming are "union". if any of the old prototypes has them the resulting prototype should
172-
get them. It happens that such a transformation shouldn't change observable behaviors.
173-
- What to do about things like page up which don't exist on laptop keyboards is a tbd question for now. Feel free to
174-
punt it.
175-
- Alternate key mappings get dropped.
176-
- Prototypes which are only modifiers, if any, can be dropped. They weren't the greatest idea in the first place, but
177-
they're for scanner and there are other keys already.
178-
- There are other prototype kinds in data.lua, just leave those alone.
179-
- To "execute" a lua file, `require('otherfile)` without assigning it to anything.
180-
- trains will come up. If possible preserve their key handlers. You can't test those. If it's unclear where it should
181-
go in the handling, put it in the else branch for now. Mostly these are being kept for documentation.
182-
183-
Concretely I recommend doing it like this. There's other ways but this is what I'd do:
184-
185-
- Make data/input.lua and require it from data.lua.
186-
- `data:extend { ... }` in it so you can start moving prototypes over.
187-
- Find the first prototype in data.lua that's an input and make the new prototype.
188-
- Write down all of the others from data.lua that match it and delete them from data.lua.
189-
- Go find all the event handlers in control.lua and cut them to another file (cut, not copy).
190-
- Paste that other file back into control.lua at the bottom.
191-
- Deal with that set.
192-
- Repeat until done.
193-
194-
## Heat Pipes
195-
196-
We need a module for heat pipes like the module for fluids. The differences are that heat pipes don't have fluidboxes
197-
or underground connections. Like this:
198-
199-
- Refactor the shape logic in fa-info and fluids.lua to be abstract enough to give you the shape of a pipe when it's not
200-
a real fluid pipe.
201-
- Write a function which can find all heat connections on an entity.
202-
- Special case heat pipe itself in this to always have one connection.
203-
- When on an entity over a heat connection probe one tile in all directions to find other entities, and check if you landed on one of their heat connections.
204-
- It looks like floats would be an issue here but all floats for heat connections are 0.5, e.g. direct equality tests actually work out.
205-
- Heat pipes aren't an exception, save that their heat connection is sort of faked out.
206-
- If it is a heat pipe, grab all other adjacent heat pipes and build the shape, then announce what it connects to that's
207-
not a heat pipe, e.g. "heat exchanger at south". Fluid code already does this, so you might be able to make it
208-
somewhat generic again.
209-
210-
In 2.0 base your entities for heat are nuclear reactors and heat exchangers. Space age adds a bunch more. To determine
211-
if an entity "participates" in heat, it is sort of enough to just find out if it has a heat connection. The only
212-
exception to that is aquilo which we will handle later because it's not something that fits in this module (indeed it
213-
may already work). Entities which participate in heat need to have their temperature read. Code for this already
214-
exists in fa-info but it may not extend to Space Age entities due to special casing off prototype types.
215-
216-
## Aquilo iceberg scanner backend
217-
218-
there are a lot of things to do with scanner that we can work on but probably the easiest is aquilo icebergs. There
219-
isn't much in this document because scanner is fully documented in devdocs/scanner.md. In practice such a backend is
220-
just an inversion of the water one, e.g. a different tile set. Don't be fooled by the resource scanner using the
221-
spatial hashes, which is sort of legacy; that can go in favor of tile-clusterer as well, but there's no pressing need to
222-
rewrite so we haven't.
223-
224-
## Test Larger Cursors on Gleba
225-
226-
This is an easy one maybe. Make a large cursor and move it over gleba and see how it crashes horribly. Hopefully it
227-
doesn't. If it does we will discuss what work needs to be done.
228-
22934
## Script to do Releases
23035

23136
This needs some scoping but since we have the spare slack it'd be a good idea. What we know wrt the flow:

locale/en/entity-info.cfg

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ ent-info-nuclear-reactor-neighbor-bonus=with neighbor bonus __1__
8484
8585
ent-info-heat-neighbors=Connects __1__
8686
ent-info-heat-neighbors-none=Connects to nothing
87+
ent-info-heat-port-1=heat to the __1__
88+
ent-info-heat-port-2=heat to the __1__ and __2__
89+
ent-info-heat-port-3=heat to the __1__, __2__ and __3__
90+
ent-info-heat-port-4=heat to the __1__, __2__, __3__ and __4__
91+
ent-info-heat-conn-1=connected to __1__ from the __2__
92+
ent-info-heat-conn-2=connected to __1__ from the __2__ and __3__ from the __4__
93+
ent-info-heat-conn-3=connected to __1__ from the __2__, __3__ from the __4__ and __5__ from the __6__
94+
ent-info-heat-conn-4=connected to __1__ from the __2__, __3__ from the __4__, __5__ from the __6__ and __7__ from the __8__
8795
8896
# Connected to west via 3 tiles underground
8997
ent-info-underground-belt-connection=Connected to __1__ via __2__ tiles underground

0 commit comments

Comments
 (0)