Skip to content

Commit 3367f6c

Browse files
committed
Add HexPattern.fromAnglesUnchecked and use it in HexPattern.CODEC
1 parent 7c5fffa commit 3367f6c

File tree

2 files changed

+65
-17
lines changed

2 files changed

+65
-17
lines changed

Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,19 @@ enum class HexAngle {
55

66
fun rotatedBy(a: HexAngle) = values()[(this.ordinal + a.ordinal) % values().size]
77
operator fun times(a: HexAngle) = this.rotatedBy(a)
8+
9+
companion object {
10+
fun fromChar(c: Char): HexAngle? {
11+
return when (c) {
12+
'w' -> FORWARD
13+
'e' -> RIGHT
14+
'd' -> RIGHT_BACK
15+
// for completeness ...
16+
's' -> BACK
17+
'a' -> LEFT_BACK
18+
'q' -> LEFT
19+
else -> null
20+
}
21+
}
22+
}
823
}

Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
99
import net.minecraft.nbt.CompoundTag
1010
import net.minecraft.nbt.Tag
1111
import net.minecraft.world.phys.Vec2
12+
import kotlin.jvm.Throws
1213

1314
/**
1415
* Sequence of angles to define a pattern traced.
@@ -130,11 +131,12 @@ data class HexPattern(val startDir: HexDir, val angles: MutableList<HexAngle> =
130131
const val TAG_ANGLES = "angles"
131132

132133
@JvmField
133-
val CODEC: Codec<HexPattern> = RecordCodecBuilder.create({instance -> instance.group(
134-
Codec.STRING.fieldOf(TAG_START_DIR).forGetter(HexPattern::anglesSignature),
135-
HexDir.CODEC.fieldOf(TAG_ANGLES).forGetter(HexPattern::startDir)
136-
).apply(instance, HexPattern::fromAngles)
137-
})
134+
val CODEC: Codec<HexPattern> = RecordCodecBuilder.create { instance ->
135+
instance.group(
136+
Codec.STRING.fieldOf(TAG_START_DIR).forGetter(HexPattern::anglesSignature),
137+
HexDir.CODEC.fieldOf(TAG_ANGLES).forGetter(HexPattern::startDir)
138+
).apply(instance, HexPattern::fromAnglesUnchecked)
139+
}
138140

139141
@JvmStatic
140142
fun isPattern(tag: CompoundTag): Boolean {
@@ -149,30 +151,61 @@ data class HexPattern(val startDir: HexDir, val angles: MutableList<HexAngle> =
149151
return HexPattern(startDir, angles.toMutableList())
150152
}
151153

154+
/**
155+
* Construct a [HexPattern] from an angle signature and starting direction.
156+
*
157+
* Throws if the signature contains an invalid character, or if the resulting pattern would contain overlaps.
158+
*/
152159
@JvmStatic
160+
@Throws(IllegalArgumentException::class, IllegalStateException::class)
153161
fun fromAngles(signature: String, startDir: HexDir): HexPattern {
154162
val out = HexPattern(startDir)
163+
164+
var cursor = HexCoord.Origin
155165
var compass = startDir
166+
val linesSeen = mutableSetOf(
167+
cursor to compass,
168+
cursor + compass to compass.rotatedBy(HexAngle.BACK),
169+
)
156170

157171
for ((idx, c) in signature.withIndex()) {
158-
val angle = when (c) {
159-
'w' -> HexAngle.FORWARD
160-
'e' -> HexAngle.RIGHT
161-
'd' -> HexAngle.RIGHT_BACK
162-
// for completeness ...
163-
's' -> HexAngle.BACK
164-
'a' -> HexAngle.LEFT_BACK
165-
'q' -> HexAngle.LEFT
166-
else -> throw IllegalArgumentException("Cannot match $c at idx $idx to a direction")
167-
}
172+
val angle = HexAngle.fromChar(c)
173+
?: throw IllegalArgumentException("Cannot match $c at idx $idx to a direction")
174+
175+
cursor += compass
168176
compass *= angle
169-
val success = out.tryAppendDir(compass)
170-
if (!success) {
177+
178+
if (
179+
!linesSeen.add(cursor to compass)
180+
// Line from here to there also blocks there to here
181+
|| !linesSeen.add(cursor + compass to compass.rotatedBy(HexAngle.BACK))
182+
) {
171183
throw IllegalStateException("Adding the angle $c at index $idx made the pattern invalid by looping back on itself")
172184
}
185+
186+
out.angles.add(angle)
173187
}
188+
174189
return out
175190
}
176191

192+
/**
193+
* Construct a [HexPattern] from an angle signature and starting direction, without checking for overlaps.
194+
*
195+
* Throws if the signature contains an invalid character.
196+
*/
197+
@JvmStatic
198+
@Throws(IllegalArgumentException::class)
199+
fun fromAnglesUnchecked(signature: String, startDir: HexDir): HexPattern {
200+
val out = HexPattern(startDir)
201+
202+
for ((idx, c) in signature.withIndex()) {
203+
val angle = HexAngle.fromChar(c)
204+
?: throw IllegalArgumentException("Cannot match $c at idx $idx to a direction")
205+
out.angles.add(angle)
206+
}
207+
208+
return out
209+
}
177210
}
178211
}

0 commit comments

Comments
 (0)