split tilesets, bed
This commit is contained in:
@@ -2,215 +2,7 @@
|
|||||||
|
|
||||||
#show raw.where(lang: "mc-diorama"): it => diorama(autoplay: true, loop: true, theta: 160, phi: 20, it.text)
|
#show raw.where(lang: "mc-diorama"): it => diorama(autoplay: true, loop: true, theta: 160, phi: 20, it.text)
|
||||||
|
|
||||||
= Preventing Interference <timing>
|
= Block Event Delay
|
||||||
|
|
||||||
The protocols as described are very sensitive to the exact timing that the EID counter is
|
|
||||||
incremented. The fundamental cause for all types of interference is that we spawn a reference and
|
|
||||||
measurement item with too much delay, and some unexpected entity (or entities) spawn in-between. To
|
|
||||||
mitigate interference, then, we need that window to be *as short as possible* while still allowing
|
|
||||||
us to spawn transmission entities in that window.
|
|
||||||
|
|
||||||
== Tilesets
|
|
||||||
|
|
||||||
```mc-diorama
|
|
||||||
p 0 -1 0 smooth_stone_slab type=top
|
|
||||||
p 1 -1 0 smooth_stone_slab type=top
|
|
||||||
p 2 -1 0 smooth_stone_slab type=top
|
|
||||||
p 3 -1 0 smooth_stone_slab type=top
|
|
||||||
p 4 -1 0 smooth_stone_slab type=top
|
|
||||||
p 0 0 0 repeater facing=west powered=false locked=false delay=1
|
|
||||||
p 1 0 0 observer facing=west powered=false
|
|
||||||
p 2 0 0 repeater facing=west powered=false locked=false delay=2
|
|
||||||
p 3 0 0 comparator facing=west powered=false mode=compare
|
|
||||||
p 4 0 0 repeater facing=west powered=false locked=false delay=1
|
|
||||||
|
|
||||||
t 2
|
|
||||||
p 0 0 0 powered=true
|
|
||||||
|
|
||||||
t 4
|
|
||||||
p 0 0 0 powered=false
|
|
||||||
p 1 0 0 powered=true
|
|
||||||
|
|
||||||
t 6
|
|
||||||
p 1 0 0 powered=false
|
|
||||||
|
|
||||||
t 8
|
|
||||||
p 2 0 0 powered=true
|
|
||||||
|
|
||||||
t 10
|
|
||||||
p 3 0 0 powered=true
|
|
||||||
|
|
||||||
t 12
|
|
||||||
p 2 0 0 powered=false
|
|
||||||
p 4 0 0 powered=true
|
|
||||||
|
|
||||||
t 14
|
|
||||||
p 3 0 0 powered=false
|
|
||||||
|
|
||||||
t 16
|
|
||||||
p 4 0 0 powered=false
|
|
||||||
|
|
||||||
t 20
|
|
||||||
p 0 0 0
|
|
||||||
```
|
|
||||||
|
|
||||||
#todo[fix tileset naming. the tileset is the *structure*. the particular sequence is just one instance of that tileset]
|
|
||||||
|
|
||||||
A *tile sequence* is a chain of redstone components that all update in the tile tick phase.
|
|
||||||
The fundamental principle here is to use tile-tick priority (TTP) to set a global order.
|
|
||||||
#link("https://youtu.be/sLftwVwqPQE")[See Charlie's great video on TTP for details].
|
|
||||||
|
|
||||||
A *tile set* is a system of constructing tile sequences that enforces a particular global ordering.
|
|
||||||
|
|
||||||
Components that activate later in the sequence have a stronger effect on the order, so to match our
|
|
||||||
left-to-right reading convention, we diagram tile sequences so the signal flows right-to-left.
|
|
||||||
|
|
||||||
=== The Tile Tick Priority Queue
|
|
||||||
|
|
||||||
The game schedules tile updates through a priority queue; different components have different
|
|
||||||
priority, so each stage of the tileset iteratively refines the global order. Across the full
|
|
||||||
tileset, we can enforce an arbitrary global ordering.
|
|
||||||
|
|
||||||
#todo[the priority table][
|
|
||||||
call out here that basic comparators and all other components, so from here on out we're just
|
|
||||||
going to use comparators for simplicity.
|
|
||||||
]
|
|
||||||
|
|
||||||
Components with different priority always update in priority order, but components with equal
|
|
||||||
priority update in scheduled order.
|
|
||||||
|
|
||||||
#todo[rephrase or remove][
|
|
||||||
The core principal is that repeaters have higher priority than other components. For example, if a
|
|
||||||
repeater and comparator are scheduled to activate in the same tick, the repeater always (with one
|
|
||||||
exception, if the comparator faces into a diode and the repeater does not) activates before the
|
|
||||||
comparator does. By choosing a regular building pattern, we can avoid this exception entirely.
|
|
||||||
|
|
||||||
// Among repeaters, they activate in the order in which they were scheduled. And among
|
|
||||||
// comparators, they activate in the order in which they are scheduled. But every repeater
|
|
||||||
// activates before any comparator (aside from that one exception). This gives us a *stable sort*
|
|
||||||
// which we can use to globally define update order with arbitrary precision.
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
#example[
|
|
||||||
#todo[this explanation is so janky]
|
|
||||||
|
|
||||||
Say these three tilesets are started in the same gametick, `t=0`.
|
|
||||||
|
|
||||||
```
|
|
||||||
<------
|
|
||||||
1 rep cmp ab
|
|
||||||
2 cmp rep cd
|
|
||||||
3 2rep e
|
|
||||||
<------
|
|
||||||
```
|
|
||||||
|
|
||||||
Once `b`, `d`, and `e` are scheduled, the priority queue looks like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
t=2 [d] [b]
|
|
||||||
t=4 [e]
|
|
||||||
```
|
|
||||||
|
|
||||||
Now at `t=2`, we process the queue in order.
|
|
||||||
|
|
||||||
- `d` activates and schedules `c`.
|
|
||||||
- `b` activates and schedules `a`.
|
|
||||||
|
|
||||||
```
|
|
||||||
t=4 [e a] [c]
|
|
||||||
```
|
|
||||||
|
|
||||||
Now at `t=4`, the end of the tileset, the lanes will always update in order `3 1 2`
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
So the full picture involves arbitrary components and priorities. As long as all the tilesets have
|
|
||||||
the same total delay and end at the same time, we can determine a global ordering. However the
|
|
||||||
general picture is hard to reason about, we basically have to simulate the priority queue to make
|
|
||||||
predictions. If we restrict the design of the tilesets a bit, there are two simplifications we could
|
|
||||||
take to make things easier to reason about.
|
|
||||||
|
|
||||||
=== Permutation Tilesets
|
|
||||||
|
|
||||||
#todo[describe the mixed delay permutation tilesets and the alphabetization procedure]
|
|
||||||
|
|
||||||
=== Binary
|
|
||||||
|
|
||||||
The simplest tilesets are made entirely of comparators and 2gt repeaters (alternatively: observers
|
|
||||||
and 2gt repeaters). Repeaters activate before comparators, so if we think of it like sorting words
|
|
||||||
alphabetically, we can identify repeaters with "A" and comparators with "B".
|
|
||||||
|
|
||||||
So, suppose we have a "binary tileset" that is 2gt long. There are two options, A and B. If we
|
|
||||||
alphabetize these, we see the A (repeater) always executes before the B (comparator). With such a
|
|
||||||
short tileset, that seems trivial; things get more interesting as we add more elements.
|
|
||||||
|
|
||||||
```
|
|
||||||
<--
|
|
||||||
cmp (B)
|
|
||||||
rep (A)
|
|
||||||
```
|
|
||||||
|
|
||||||
Now let's use 2 components for a 4gt tileset. There are now four options, AA, AB, BA, BB. We can
|
|
||||||
alphabetize these and see the order.
|
|
||||||
|
|
||||||
```
|
|
||||||
<------
|
|
||||||
cmp cmp (BB)
|
|
||||||
cmp rep (BA)
|
|
||||||
rep cmp (AB)
|
|
||||||
rep rep (AA)
|
|
||||||
```
|
|
||||||
|
|
||||||
To break this down: the bottom two (AA, AB) end in repeaters, so they must come first. Among those,
|
|
||||||
(AA) comes first. Among the top two (BA, BB), (BA) comes first. It's standard alphabetizing. Just as
|
|
||||||
the order of the alphabet creates an ordering over all words, the ordering of the comparator and
|
|
||||||
repeater creates an ordering of all tilesets.
|
|
||||||
|
|
||||||
The 6gt tileset. There are now eight options.
|
|
||||||
|
|
||||||
```
|
|
||||||
<---------
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
As the tilesets get larger, it's less useful to lay out the entire tileset and more useful to find
|
|
||||||
the next and previous lanes.
|
|
||||||
|
|
||||||
For example, take this 7-diode tileset.
|
|
||||||
|
|
||||||
```
|
|
||||||
cmp rep rep cmp rep cmp cmp
|
|
||||||
<--------------------------
|
|
||||||
B A A B A B B
|
|
||||||
```
|
|
||||||
|
|
||||||
We can easily find the next lane by thinking of this not as a *word* but as a *number*. We have two
|
|
||||||
options, and one is greater than the other.
|
|
||||||
|
|
||||||
```
|
|
||||||
cmp rep rep cmp rep cmp cmp
|
|
||||||
<--------------------------
|
|
||||||
B A A B A B B
|
|
||||||
1 0 0 1 0 1 1
|
|
||||||
```
|
|
||||||
|
|
||||||
We can think of this tileset as a 7-bit binary number, in this case the value 75. We can find the
|
|
||||||
next lane by simply incrementing by one.
|
|
||||||
|
|
||||||
```
|
|
||||||
1 0 0 1 0 1 1 (75)
|
|
||||||
+ 1
|
|
||||||
1 0 0 1 1 0 0 (76)
|
|
||||||
<--------------------------
|
|
||||||
cmp rep rep cmp cmp rep rep
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Lexicographic
|
|
||||||
|
|
||||||
=== Jamming
|
|
||||||
|
|
||||||
== Block Event Delay
|
|
||||||
|
|
||||||
Block Event Delay is not a complete substitute for tilesets, but it can significantly reduce the
|
Block Event Delay is not a complete substitute for tilesets, but it can significantly reduce the
|
||||||
required length of tilesets and compact repetetive systems. It is based on a behavior of piston push
|
required length of tilesets and compact repetetive systems. It is based on a behavior of piston push
|
||||||
@@ -247,7 +39,6 @@ p 4 -1 -1 piston facing=up extended=false
|
|||||||
p 4 0 -2 observer facing=south powered=false
|
p 4 0 -2 observer facing=south powered=false
|
||||||
p 4 0 0 light_gray_terracotta
|
p 4 0 0 light_gray_terracotta
|
||||||
p 4 1 0 redstone_wire east=side west=side power=0
|
p 4 1 0 redstone_wire east=side west=side power=0
|
||||||
|
|
||||||
t 0
|
t 0
|
||||||
p -1 0 0 powered=true
|
p -1 0 0 powered=true
|
||||||
p 0 1 0 power=15
|
p 0 1 0 power=15
|
||||||
@@ -255,7 +46,6 @@ p 1 1 0 power=14
|
|||||||
p 2 1 0 power=13
|
p 2 1 0 power=13
|
||||||
p 3 1 0 power=12
|
p 3 1 0 power=12
|
||||||
p 4 1 0 power=11
|
p 4 1 0 power=11
|
||||||
|
|
||||||
t 1
|
t 1
|
||||||
p 0 0 -1 extended=true
|
p 0 0 -1 extended=true
|
||||||
p 0 -0.5 -1 piston_head facing=down short=true type=normal
|
p 0 -0.5 -1 piston_head facing=down short=true type=normal
|
||||||
@@ -267,7 +57,6 @@ p 3 -1 -1 extended=true
|
|||||||
p 3 -0.5 -1 piston_head facing=up short=true type=normal
|
p 3 -0.5 -1 piston_head facing=up short=true type=normal
|
||||||
p 4 -1 -1 extended=true
|
p 4 -1 -1 extended=true
|
||||||
p 4 -0.5 -1 piston_head facing=up short=true type=normal
|
p 4 -0.5 -1 piston_head facing=up short=true type=normal
|
||||||
|
|
||||||
t 2
|
t 2
|
||||||
p -1 0 0 powered=false
|
p -1 0 0 powered=false
|
||||||
p 0 1 0 power=0
|
p 0 1 0 power=0
|
||||||
@@ -289,7 +78,6 @@ p 1 0 -2 powered=true
|
|||||||
p 2 0 -2 powered=true
|
p 2 0 -2 powered=true
|
||||||
p 3 0 -2 powered=true
|
p 3 0 -2 powered=true
|
||||||
p 4 0 -2 powered=true
|
p 4 0 -2 powered=true
|
||||||
|
|
||||||
t 3
|
t 3
|
||||||
p 0 -1 -1 air
|
p 0 -1 -1 air
|
||||||
p 1 0 -1 air
|
p 1 0 -1 air
|
||||||
@@ -301,7 +89,6 @@ p 1 -0.5 -1 piston_head facing=up short=true type=normal
|
|||||||
p 2 -0.5 -1 piston_head facing=up short=true type=normal
|
p 2 -0.5 -1 piston_head facing=up short=true type=normal
|
||||||
p 3 -0.5 -1 piston_head facing=up short=true type=normal
|
p 3 -0.5 -1 piston_head facing=up short=true type=normal
|
||||||
p 4 -0.5 -1 piston_head facing=up short=true type=normal
|
p 4 -0.5 -1 piston_head facing=up short=true type=normal
|
||||||
|
|
||||||
t 4
|
t 4
|
||||||
p 0 -0.5 -1 air
|
p 0 -0.5 -1 air
|
||||||
p 1 -0.5 -1 air
|
p 1 -0.5 -1 air
|
||||||
@@ -317,7 +104,6 @@ p 1 0 -2 powered=false
|
|||||||
p 2 0 -2 powered=false
|
p 2 0 -2 powered=false
|
||||||
p 3 0 -2 powered=false
|
p 3 0 -2 powered=false
|
||||||
p 4 0 -2 powered=false
|
p 4 0 -2 powered=false
|
||||||
|
|
||||||
t 20
|
t 20
|
||||||
p 0 0 0
|
p 0 0 0
|
||||||
```
|
```
|
||||||
@@ -425,22 +211,18 @@ p 1 1 8 redstone_wire east=side west=side power=0
|
|||||||
p 2 1 8 redstone_wire east=side west=side power=0
|
p 2 1 8 redstone_wire east=side west=side power=0
|
||||||
p 3 1 8 redstone_wire east=side west=side power=0
|
p 3 1 8 redstone_wire east=side west=side power=0
|
||||||
p 4 1 8 redstone_wire east=side west=side power=0
|
p 4 1 8 redstone_wire east=side west=side power=0
|
||||||
|
|
||||||
t 1
|
t 1
|
||||||
p -3 0 0 powered=true
|
p -3 0 0 powered=true
|
||||||
p -3 0 4 powered=true
|
p -3 0 4 powered=true
|
||||||
p 7 0 8 powered=true
|
p 7 0 8 powered=true
|
||||||
|
|
||||||
t 3
|
t 3
|
||||||
p -2 0 0 powered=true
|
p -2 0 0 powered=true
|
||||||
p -2 0 4 powered=true
|
p -2 0 4 powered=true
|
||||||
p 6 0 8 powered=true
|
p 6 0 8 powered=true
|
||||||
|
|
||||||
t 6
|
t 6
|
||||||
p -3 0 0 powered=false
|
p -3 0 0 powered=false
|
||||||
p -3 0 4 powered=false
|
p -3 0 4 powered=false
|
||||||
p 7 0 8 powered=false
|
p 7 0 8 powered=false
|
||||||
|
|
||||||
t 8
|
t 8
|
||||||
p 5 0 8 powered=true
|
p 5 0 8 powered=true
|
||||||
p 0 1 8 power=15
|
p 0 1 8 power=15
|
||||||
@@ -448,7 +230,6 @@ p 1 1 8 power=14
|
|||||||
p 2 1 8 power=13
|
p 2 1 8 power=13
|
||||||
p 3 1 8 power=12
|
p 3 1 8 power=12
|
||||||
p 4 1 8 power=11
|
p 4 1 8 power=11
|
||||||
|
|
||||||
t 9
|
t 9
|
||||||
p -1 0 4 powered=true
|
p -1 0 4 powered=true
|
||||||
p 0 1 4 power=15
|
p 0 1 4 power=15
|
||||||
@@ -456,7 +237,6 @@ p 1 1 4 power=14
|
|||||||
p 2 1 4 power=13
|
p 2 1 4 power=13
|
||||||
p 3 1 4 power=12
|
p 3 1 4 power=12
|
||||||
p 4 1 4 power=11
|
p 4 1 4 power=11
|
||||||
|
|
||||||
t 10
|
t 10
|
||||||
p -1 0 0 powered=true
|
p -1 0 0 powered=true
|
||||||
p 0 1 0 power=11
|
p 0 1 0 power=11
|
||||||
@@ -464,72 +244,55 @@ p 1 1 0 power=12
|
|||||||
p 2 1 0 power=13
|
p 2 1 0 power=13
|
||||||
p 3 1 0 power=14
|
p 3 1 0 power=14
|
||||||
p 4 1 0 power=15
|
p 4 1 0 power=15
|
||||||
|
|
||||||
t 11
|
t 11
|
||||||
p 4 0 7 extended=true
|
p 4 0 7 extended=true
|
||||||
p 4 -1 7 piston_head type=normal facing=down short=false
|
p 4 -1 7 piston_head type=normal facing=down short=false
|
||||||
|
|
||||||
t 12
|
t 12
|
||||||
p 4 0 3 extended=true
|
p 4 0 3 extended=true
|
||||||
p 4 -1 3 piston_head type=normal facing=down short=false
|
p 4 -1 3 piston_head type=normal facing=down short=false
|
||||||
|
|
||||||
t 13
|
t 13
|
||||||
p 4 0 -1 extended=true
|
p 4 0 -1 extended=true
|
||||||
p 4 -1 -1 piston_head type=normal facing=down short=false
|
p 4 -1 -1 piston_head type=normal facing=down short=false
|
||||||
|
|
||||||
t 14
|
t 14
|
||||||
p 3 -1 7 extended=true
|
p 3 -1 7 extended=true
|
||||||
p 3 0 7 piston_head type=normal facing=up short=false
|
p 3 0 7 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 15
|
t 15
|
||||||
p 3 -1 3 extended=true
|
p 3 -1 3 extended=true
|
||||||
p 3 0 3 piston_head type=normal facing=up short=false
|
p 3 0 3 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 16
|
t 16
|
||||||
p 3 -1 -1 extended=true
|
p 3 -1 -1 extended=true
|
||||||
p 3 0 -1 piston_head type=normal facing=up short=false
|
p 3 0 -1 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 17
|
t 17
|
||||||
p 2 -1 7 extended=true
|
p 2 -1 7 extended=true
|
||||||
p 2 0 7 piston_head type=normal facing=up short=false
|
p 2 0 7 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 18
|
t 18
|
||||||
p 2 -1 3 extended=true
|
p 2 -1 3 extended=true
|
||||||
p 2 0 3 piston_head type=normal facing=up short=false
|
p 2 0 3 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 19
|
t 19
|
||||||
p 2 -1 -1 extended=true
|
p 2 -1 -1 extended=true
|
||||||
p 2 0 -1 piston_head type=normal facing=up short=false
|
p 2 0 -1 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 20
|
t 20
|
||||||
p 1 -1 7 extended=true
|
p 1 -1 7 extended=true
|
||||||
p 1 0 7 piston_head type=normal facing=up short=false
|
p 1 0 7 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 21
|
t 21
|
||||||
p 1 -1 3 extended=true
|
p 1 -1 3 extended=true
|
||||||
p 1 0 3 piston_head type=normal facing=up short=false
|
p 1 0 3 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 22
|
t 22
|
||||||
p 1 -1 -1 extended=true
|
p 1 -1 -1 extended=true
|
||||||
p 1 0 -1 piston_head type=normal facing=up short=false
|
p 1 0 -1 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 23
|
t 23
|
||||||
p 0 -1 7 extended=true
|
p 0 -1 7 extended=true
|
||||||
p 0 0 7 piston_head type=normal facing=up short=false
|
p 0 0 7 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 24
|
t 24
|
||||||
p 0 -1 3 extended=true
|
p 0 -1 3 extended=true
|
||||||
p 0 0 3 piston_head type=normal facing=up short=false
|
p 0 0 3 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 25
|
t 25
|
||||||
p 0 -1 -1 extended=true
|
p 0 -1 -1 extended=true
|
||||||
p 0 0 -1 piston_head type=normal facing=up short=false
|
p 0 0 -1 piston_head type=normal facing=up short=false
|
||||||
|
|
||||||
t 26
|
t 26
|
||||||
p -2 0 0 powered=false
|
p -2 0 0 powered=false
|
||||||
p -2 0 4 powered=false
|
p -2 0 4 powered=false
|
||||||
p 6 0 8 powered=false
|
p 6 0 8 powered=false
|
||||||
|
|
||||||
t 28
|
t 28
|
||||||
p 5 0 8 powered=false
|
p 5 0 8 powered=false
|
||||||
p 0 1 8 power=0
|
p 0 1 8 power=0
|
||||||
@@ -537,7 +300,6 @@ p 1 1 8 power=0
|
|||||||
p 2 1 8 power=0
|
p 2 1 8 power=0
|
||||||
p 3 1 8 power=0
|
p 3 1 8 power=0
|
||||||
p 4 1 8 power=0
|
p 4 1 8 power=0
|
||||||
|
|
||||||
t 29
|
t 29
|
||||||
p -1 0 4 powered=false
|
p -1 0 4 powered=false
|
||||||
p 0 1 4 power=0
|
p 0 1 4 power=0
|
||||||
@@ -545,7 +307,6 @@ p 1 1 4 power=0
|
|||||||
p 2 1 4 power=0
|
p 2 1 4 power=0
|
||||||
p 3 1 4 power=0
|
p 3 1 4 power=0
|
||||||
p 4 1 4 power=0
|
p 4 1 4 power=0
|
||||||
|
|
||||||
t 30
|
t 30
|
||||||
p -1 0 0 powered=false
|
p -1 0 0 powered=false
|
||||||
p 0 1 0 power=0
|
p 0 1 0 power=0
|
||||||
@@ -553,139 +314,99 @@ p 1 1 0 power=0
|
|||||||
p 2 1 0 power=0
|
p 2 1 0 power=0
|
||||||
p 3 1 0 power=0
|
p 3 1 0 power=0
|
||||||
p 4 1 0 power=0
|
p 4 1 0 power=0
|
||||||
|
|
||||||
t 31
|
t 31
|
||||||
p 3 0 6 powered=true
|
p 3 0 6 powered=true
|
||||||
|
|
||||||
t 32
|
t 32
|
||||||
p 3 0 2 powered=true
|
p 3 0 2 powered=true
|
||||||
|
|
||||||
t 33
|
t 33
|
||||||
p 3 0 -2 powered=true
|
p 3 0 -2 powered=true
|
||||||
|
|
||||||
t 34
|
t 34
|
||||||
p 2 0 6 powered=true
|
p 2 0 6 powered=true
|
||||||
|
|
||||||
t 35
|
t 35
|
||||||
p 2 0 2 powered=true
|
p 2 0 2 powered=true
|
||||||
|
|
||||||
t 36
|
t 36
|
||||||
p 2 0 -2 powered=true
|
p 2 0 -2 powered=true
|
||||||
|
|
||||||
t 37
|
t 37
|
||||||
p 1 0 6 powered=true
|
p 1 0 6 powered=true
|
||||||
|
|
||||||
t 38
|
t 38
|
||||||
p 1 0 2 powered=true
|
p 1 0 2 powered=true
|
||||||
|
|
||||||
t 39
|
t 39
|
||||||
p 1 0 -2 powered=true
|
p 1 0 -2 powered=true
|
||||||
|
|
||||||
t 40
|
t 40
|
||||||
p 0 0 6 powered=true
|
p 0 0 6 powered=true
|
||||||
|
|
||||||
t 41
|
t 41
|
||||||
p 0 0 2 powered=true
|
p 0 0 2 powered=true
|
||||||
|
|
||||||
t 42
|
t 42
|
||||||
p 0 0 -2 powered=true
|
p 0 0 -2 powered=true
|
||||||
|
|
||||||
t 43
|
t 43
|
||||||
p 4 0 7 extended=false
|
p 4 0 7 extended=false
|
||||||
p 4 -1 7 air
|
p 4 -1 7 air
|
||||||
|
|
||||||
t 44
|
t 44
|
||||||
p 4 0 3 extended=false
|
p 4 0 3 extended=false
|
||||||
p 4 -1 3 air
|
p 4 -1 3 air
|
||||||
|
|
||||||
t 45
|
t 45
|
||||||
p 4 0 -1 extended=false
|
p 4 0 -1 extended=false
|
||||||
p 4 -1 -1 air
|
p 4 -1 -1 air
|
||||||
|
|
||||||
t 46
|
t 46
|
||||||
p 3 -1 7 extended=false
|
p 3 -1 7 extended=false
|
||||||
p 3 0 7 air
|
p 3 0 7 air
|
||||||
|
|
||||||
t 47
|
t 47
|
||||||
p 3 -1 3 extended=false
|
p 3 -1 3 extended=false
|
||||||
p 3 0 3 air
|
p 3 0 3 air
|
||||||
|
|
||||||
t 48
|
t 48
|
||||||
p 3 -1 -1 extended=false
|
p 3 -1 -1 extended=false
|
||||||
p 3 0 -1 air
|
p 3 0 -1 air
|
||||||
|
|
||||||
t 49
|
t 49
|
||||||
p 2 -1 7 extended=false
|
p 2 -1 7 extended=false
|
||||||
p 2 0 7 air
|
p 2 0 7 air
|
||||||
|
|
||||||
t 50
|
t 50
|
||||||
p 2 -1 3 extended=false
|
p 2 -1 3 extended=false
|
||||||
p 2 0 3 air
|
p 2 0 3 air
|
||||||
|
|
||||||
t 51
|
t 51
|
||||||
p 2 -1 -1 extended=false
|
p 2 -1 -1 extended=false
|
||||||
p 2 0 -1 air
|
p 2 0 -1 air
|
||||||
|
|
||||||
t 52
|
t 52
|
||||||
p 1 -1 7 extended=false
|
p 1 -1 7 extended=false
|
||||||
p 1 0 7 air
|
p 1 0 7 air
|
||||||
|
|
||||||
t 53
|
t 53
|
||||||
p 1 -1 3 extended=false
|
p 1 -1 3 extended=false
|
||||||
p 1 0 3 air
|
p 1 0 3 air
|
||||||
|
|
||||||
t 54
|
t 54
|
||||||
p 1 -1 -1 extended=false
|
p 1 -1 -1 extended=false
|
||||||
p 1 0 -1 air
|
p 1 0 -1 air
|
||||||
|
|
||||||
t 55
|
t 55
|
||||||
p 0 -1 7 extended=false
|
p 0 -1 7 extended=false
|
||||||
p 0 0 7 air
|
p 0 0 7 air
|
||||||
|
|
||||||
t 56
|
t 56
|
||||||
p 0 -1 3 extended=false
|
p 0 -1 3 extended=false
|
||||||
p 0 0 3 air
|
p 0 0 3 air
|
||||||
|
|
||||||
t 57
|
t 57
|
||||||
p 0 -1 -1 extended=false
|
p 0 -1 -1 extended=false
|
||||||
p 0 0 -1 air
|
p 0 0 -1 air
|
||||||
|
|
||||||
t 58
|
t 58
|
||||||
p 3 0 6 powered=false
|
p 3 0 6 powered=false
|
||||||
|
|
||||||
t 59
|
t 59
|
||||||
p 3 0 2 powered=false
|
p 3 0 2 powered=false
|
||||||
|
|
||||||
t 60
|
t 60
|
||||||
p 3 0 -2 powered=false
|
p 3 0 -2 powered=false
|
||||||
|
|
||||||
t 61
|
t 61
|
||||||
p 2 0 6 powered=false
|
p 2 0 6 powered=false
|
||||||
|
|
||||||
t 62
|
t 62
|
||||||
p 2 0 2 powered=false
|
p 2 0 2 powered=false
|
||||||
|
|
||||||
t 63
|
t 63
|
||||||
p 2 0 -2 powered=false
|
p 2 0 -2 powered=false
|
||||||
|
|
||||||
t 64
|
t 64
|
||||||
p 1 0 6 powered=false
|
p 1 0 6 powered=false
|
||||||
|
|
||||||
t 65
|
t 65
|
||||||
p 1 0 2 powered=false
|
p 1 0 2 powered=false
|
||||||
|
|
||||||
t 66
|
t 66
|
||||||
p 1 0 -2 powered=false
|
p 1 0 -2 powered=false
|
||||||
|
|
||||||
t 67
|
t 67
|
||||||
p 0 0 6 powered=false
|
p 0 0 6 powered=false
|
||||||
|
|
||||||
t 68
|
t 68
|
||||||
p 0 0 2 powered=false
|
p 0 0 2 powered=false
|
||||||
|
|
||||||
t 69
|
t 69
|
||||||
p 0 0 -2 powered=false
|
p 0 0 -2 powered=false
|
||||||
|
|
||||||
t 72
|
t 72
|
||||||
p 0 0 0
|
p 0 0 0
|
||||||
```
|
```
|
||||||
@@ -14,7 +14,7 @@ surprising. An exhaustive list is available at
|
|||||||
In general, the solution is to spawn our item entities at nearly the same time, so there is no
|
In general, the solution is to spawn our item entities at nearly the same time, so there is no
|
||||||
chance for other entities to spawn in-between. For example, by spawning all items with droppers in
|
chance for other entities to spawn in-between. For example, by spawning all items with droppers in
|
||||||
the same game tick, all the items are created in the same tick phase, so player inputs and world
|
the same game tick, all the items are created in the same tick phase, so player inputs and world
|
||||||
events cannot affect it. See @timing for details.
|
events cannot affect it. See @tilesets for details.
|
||||||
|
|
||||||
== Singleplayer (before 26.2) <singleplayer>
|
== Singleplayer (before 26.2) <singleplayer>
|
||||||
|
|
||||||
202
content/tilesets.typ
Normal file
202
content/tilesets.typ
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
#import "/lib.typ": diorama, example, note, todo
|
||||||
|
|
||||||
|
#show raw.where(lang: "mc-diorama"): it => diorama(autoplay: true, loop: true, theta: 160, phi: 20, it.text)
|
||||||
|
|
||||||
|
= Tilesets <tilesets>
|
||||||
|
|
||||||
|
The protocols as described are very sensitive to the exact timing that the EID counter is
|
||||||
|
incremented. The fundamental cause for all types of interference is that we spawn a reference and
|
||||||
|
measurement item with too much delay, and some unexpected entity (or entities) spawn in-between. To
|
||||||
|
mitigate interference, then, we need that window to be *as short as possible* while still allowing
|
||||||
|
us to spawn transmission entities in that window.
|
||||||
|
|
||||||
|
We use the tile tick priority queue to define a global order of sub-tick execution.
|
||||||
|
|
||||||
|
```mc-diorama
|
||||||
|
p 0 -1 0 smooth_stone_slab type=top
|
||||||
|
p 1 -1 0 smooth_stone_slab type=top
|
||||||
|
p 2 -1 0 smooth_stone_slab type=top
|
||||||
|
p 3 -1 0 smooth_stone_slab type=top
|
||||||
|
p 4 -1 0 smooth_stone_slab type=top
|
||||||
|
p 0 0 0 repeater facing=west powered=false locked=false delay=1
|
||||||
|
p 1 0 0 observer facing=west powered=false
|
||||||
|
p 2 0 0 repeater facing=west powered=false locked=false delay=2
|
||||||
|
p 3 0 0 comparator facing=west powered=false mode=compare
|
||||||
|
p 4 0 0 repeater facing=west powered=false locked=false delay=1
|
||||||
|
t 2
|
||||||
|
p 0 0 0 powered=true
|
||||||
|
t 4
|
||||||
|
p 0 0 0 powered=false
|
||||||
|
p 1 0 0 powered=true
|
||||||
|
t 6
|
||||||
|
p 1 0 0 powered=false
|
||||||
|
t 8
|
||||||
|
p 2 0 0 powered=true
|
||||||
|
t 10
|
||||||
|
p 3 0 0 powered=true
|
||||||
|
t 12
|
||||||
|
p 2 0 0 powered=false
|
||||||
|
p 4 0 0 powered=true
|
||||||
|
t 14
|
||||||
|
p 3 0 0 powered=false
|
||||||
|
t 16
|
||||||
|
p 4 0 0 powered=false
|
||||||
|
t 20
|
||||||
|
p 0 0 0
|
||||||
|
```
|
||||||
|
|
||||||
|
#todo[fix tileset naming. the tileset is the *structure*. the particular sequence is just one instance of that tileset]
|
||||||
|
|
||||||
|
A *tile sequence* is a chain of redstone components that all update in the tile tick phase.
|
||||||
|
The fundamental principle here is to use tile-tick priority (TTP) to set a global order.
|
||||||
|
#link("https://youtu.be/sLftwVwqPQE")[See Charlie's great video on TTP for details].
|
||||||
|
|
||||||
|
A *tile set* is a system of constructing tile sequences that enforces a particular global ordering.
|
||||||
|
|
||||||
|
Components that activate later in the sequence have a stronger effect on the order, so to match our
|
||||||
|
left-to-right reading convention, we diagram tile sequences so the signal flows right-to-left.
|
||||||
|
|
||||||
|
== The Tile Tick Priority Queue
|
||||||
|
|
||||||
|
The game schedules tile updates through a priority queue; different components have different
|
||||||
|
priority, so each stage of the tileset iteratively refines the global order. Across the full
|
||||||
|
tileset, we can enforce an arbitrary global ordering.
|
||||||
|
|
||||||
|
#todo[the priority table][
|
||||||
|
call out here that basic comparators and all other components, so from here on out we're just
|
||||||
|
going to use comparators for simplicity.
|
||||||
|
]
|
||||||
|
|
||||||
|
Components with different priority always update in priority order, but components with equal
|
||||||
|
priority update in scheduled order.
|
||||||
|
|
||||||
|
#todo[rephrase or remove][
|
||||||
|
The core principal is that repeaters have higher priority than other components. For example, if a
|
||||||
|
repeater and comparator are scheduled to activate in the same tick, the repeater always (with one
|
||||||
|
exception, if the comparator faces into a diode and the repeater does not) activates before the
|
||||||
|
comparator does. By choosing a regular building pattern, we can avoid this exception entirely.
|
||||||
|
|
||||||
|
// Among repeaters, they activate in the order in which they were scheduled. And among
|
||||||
|
// comparators, they activate in the order in which they are scheduled. But every repeater
|
||||||
|
// activates before any comparator (aside from that one exception). This gives us a *stable sort*
|
||||||
|
// which we can use to globally define update order with arbitrary precision.
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
#example[
|
||||||
|
#todo[this explanation is so janky]
|
||||||
|
|
||||||
|
Say these three tilesets are started in the same gametick, `t=0`.
|
||||||
|
|
||||||
|
```
|
||||||
|
<------
|
||||||
|
1 rep cmp ab
|
||||||
|
2 cmp rep cd
|
||||||
|
3 2rep e
|
||||||
|
<------
|
||||||
|
```
|
||||||
|
|
||||||
|
Once `b`, `d`, and `e` are scheduled, the priority queue looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
t=2 [d] [b]
|
||||||
|
t=4 [e]
|
||||||
|
```
|
||||||
|
|
||||||
|
Now at `t=2`, we process the queue in order.
|
||||||
|
|
||||||
|
- `d` activates and schedules `c`.
|
||||||
|
- `b` activates and schedules `a`.
|
||||||
|
|
||||||
|
```
|
||||||
|
t=4 [e a] [c]
|
||||||
|
```
|
||||||
|
|
||||||
|
Now at `t=4`, the end of the tileset, the lanes will always update in order `3 1 2`
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
So the full picture involves arbitrary components and priorities. As long as all the tilesets have
|
||||||
|
the same total delay and end at the same time, we can determine a global ordering. However the
|
||||||
|
general picture is hard to reason about, we basically have to simulate the priority queue to make
|
||||||
|
predictions. If we restrict the design of the tilesets a bit, there are two simplifications we could
|
||||||
|
take to make things easier to reason about.
|
||||||
|
|
||||||
|
== Permutation Tilesets
|
||||||
|
|
||||||
|
#todo[describe the mixed delay permutation tilesets and the alphabetization procedure]
|
||||||
|
|
||||||
|
== Binary Tilesets
|
||||||
|
|
||||||
|
The simplest tilesets are made entirely of comparators and 2gt repeaters (alternatively: observers
|
||||||
|
and 2gt repeaters). Repeaters activate before comparators, so if we think of it like sorting words
|
||||||
|
alphabetically, we can identify repeaters with "A" and comparators with "B".
|
||||||
|
|
||||||
|
So, suppose we have a "binary tileset" that is 2gt long. There are two options, A and B. If we
|
||||||
|
alphabetize these, we see the A (repeater) always executes before the B (comparator). With such a
|
||||||
|
short tileset, that seems trivial; things get more interesting as we add more elements.
|
||||||
|
|
||||||
|
```
|
||||||
|
<--
|
||||||
|
cmp (B)
|
||||||
|
rep (A)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now let's use 2 components for a 4gt tileset. There are now four options, AA, AB, BA, BB. We can
|
||||||
|
alphabetize these and see the order.
|
||||||
|
|
||||||
|
```
|
||||||
|
<------
|
||||||
|
cmp cmp (BB)
|
||||||
|
cmp rep (BA)
|
||||||
|
rep cmp (AB)
|
||||||
|
rep rep (AA)
|
||||||
|
```
|
||||||
|
|
||||||
|
To break this down: the bottom two (AA, AB) end in repeaters, so they must come first. Among those,
|
||||||
|
(AA) comes first. Among the top two (BA, BB), (BA) comes first. It's standard alphabetizing. Just as
|
||||||
|
the order of the alphabet creates an ordering over all words, the ordering of the comparator and
|
||||||
|
repeater creates an ordering of all tilesets.
|
||||||
|
|
||||||
|
The 6gt tileset. There are now eight options.
|
||||||
|
|
||||||
|
```
|
||||||
|
<---------
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
As the tilesets get larger, it's less useful to lay out the entire tileset and more useful to find
|
||||||
|
the next and previous lanes.
|
||||||
|
|
||||||
|
For example, take this 7-diode tileset.
|
||||||
|
|
||||||
|
```
|
||||||
|
cmp rep rep cmp rep cmp cmp
|
||||||
|
<--------------------------
|
||||||
|
B A A B A B B
|
||||||
|
```
|
||||||
|
|
||||||
|
We can easily find the next lane by thinking of this not as a *word* but as a *number*. We have two
|
||||||
|
options, and one is greater than the other.
|
||||||
|
|
||||||
|
```
|
||||||
|
cmp rep rep cmp rep cmp cmp
|
||||||
|
<--------------------------
|
||||||
|
B A A B A B B
|
||||||
|
1 0 0 1 0 1 1
|
||||||
|
```
|
||||||
|
|
||||||
|
We can think of this tileset as a 7-bit binary number, in this case the value 75. We can find the
|
||||||
|
next lane by simply incrementing by one.
|
||||||
|
|
||||||
|
```
|
||||||
|
1 0 0 1 0 1 1 (75)
|
||||||
|
+ 1
|
||||||
|
1 0 0 1 1 0 0 (76)
|
||||||
|
<--------------------------
|
||||||
|
cmp rep rep cmp cmp rep rep
|
||||||
|
```
|
||||||
|
|
||||||
|
== Lexicographic Tilesets
|
||||||
|
|
||||||
|
== Jamming
|
||||||
3
lib.typ
3
lib.typ
@@ -14,8 +14,7 @@
|
|||||||
#let note = callout.with(kind: "note", label: "Note")
|
#let note = callout.with(kind: "note", label: "Note")
|
||||||
|
|
||||||
#let todo(label, ..args) = {
|
#let todo(label, ..args) = {
|
||||||
// callout(args.pos().join(), kind: "todo", label: "[TODO] " + label, outlined: true)
|
callout(args.pos().join(), kind: "todo", label: "[TODO] " + label, outlined: true)
|
||||||
none
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#let example(body) = todo("example", body)
|
#let example(body) = todo("example", body)
|
||||||
|
|||||||
5
main.typ
5
main.typ
@@ -21,8 +21,9 @@
|
|||||||
doc("index.html", include "content/index.typ")
|
doc("index.html", include "content/index.typ")
|
||||||
doc("core.html", include "content/core.typ")
|
doc("core.html", include "content/core.typ")
|
||||||
// doc("data-protocols.html", include "content/data-protocols.typ")
|
// doc("data-protocols.html", include "content/data-protocols.typ")
|
||||||
doc("interference-causes.html", include "content/interference-causes.typ")
|
doc("interference.html", include "content/interference.typ")
|
||||||
doc("interference-fixes.html", include "content/interference-fixes.typ")
|
doc("tilesets.html", include "content/tilesets.typ")
|
||||||
|
doc("block-event-delay.html", include "content/block-event-delay.typ")
|
||||||
// doc("design-notes.html", include "content/design.typ")
|
// doc("design-notes.html", include "content/design.typ")
|
||||||
// doc("channel-selectors.html", include "content/channels.typ")
|
// doc("channel-selectors.html", include "content/channels.typ")
|
||||||
// doc("bulk-transmission.html", include "content/bulk.typ")
|
// doc("bulk-transmission.html", include "content/bulk.typ")
|
||||||
|
|||||||
Reference in New Issue
Block a user