-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
332 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
src/main/kotlin/net/mcbrawls/blueprint/region/CompoundRegion.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package net.mcbrawls.blueprint.region | ||
|
||
import com.mojang.serialization.Codec | ||
import com.mojang.serialization.codecs.RecordCodecBuilder | ||
import net.mcbrawls.blueprint.region.serialization.SerializableRegion | ||
import net.minecraft.entity.Entity | ||
import net.minecraft.util.math.BlockPos | ||
|
||
/** | ||
* A region defined of multiple other regions. | ||
* Useful for regions which cannot be defined through a single format. | ||
*/ | ||
data class CompoundRegion( | ||
/** | ||
* The regions which compose this compound region. | ||
*/ | ||
val regions: List<SerializableRegion> | ||
) : Region { | ||
constructor(vararg regions: SerializableRegion) : this(regions.toList()) | ||
|
||
override val positions: Set<BlockPos> = regions.flatMap(SerializableRegion::positions).toSet() | ||
|
||
override fun contains(entity: Entity): Boolean { | ||
return regions.any { region -> region.contains(entity) } | ||
} | ||
|
||
companion object { | ||
/** | ||
* The codec of a compound region. | ||
*/ | ||
val CODEC: Codec<CompoundRegion> = RecordCodecBuilder.create { instance -> | ||
instance.group( | ||
SerializableRegion.CODEC.listOf() | ||
.fieldOf("regions") | ||
.forGetter(CompoundRegion::regions) | ||
).apply(instance, ::CompoundRegion) | ||
} | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
src/main/kotlin/net/mcbrawls/blueprint/region/CuboidRegion.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package net.mcbrawls.blueprint.region | ||
|
||
import com.mojang.serialization.Codec | ||
import com.mojang.serialization.codecs.RecordCodecBuilder | ||
import net.mcbrawls.blueprint.region.Region.Companion.iterateBoxBlockPositions | ||
import net.mcbrawls.blueprint.region.serialization.SerializableRegion | ||
import net.mcbrawls.blueprint.region.serialization.SerializableRegionTypes | ||
import net.minecraft.entity.Entity | ||
import net.minecraft.util.math.BlockPos | ||
import net.minecraft.util.math.Box | ||
import net.minecraft.util.math.Vec3d | ||
|
||
/** | ||
* A region defined by a cuboid. | ||
*/ | ||
data class CuboidRegion( | ||
/** | ||
* The root position of the region. | ||
*/ | ||
val rootPosition: Vec3d, | ||
|
||
/** | ||
* The size of the cuboid, expanding from the root position. | ||
*/ | ||
val size: Vec3d | ||
) : SerializableRegion(SerializableRegionTypes.CUBOID) { | ||
/** | ||
* The cached box of this cuboid region. | ||
*/ | ||
private val box: Box = createBox() | ||
|
||
override val positions: Set<BlockPos> = computePositions() | ||
|
||
/** | ||
* A predicate to check if an entity is within the cuboid bounding box. | ||
*/ | ||
override fun contains(entity: Entity): Boolean { | ||
return entity.boundingBox.intersects(box) | ||
} | ||
|
||
/** | ||
* Creates a box of this cuboid region. | ||
*/ | ||
private fun createBox(): Box { | ||
val rootBox = Box.from(rootPosition) | ||
|
||
val endPosition = rootPosition.add(size) | ||
val endBox = Box.from(endPosition) | ||
|
||
return rootBox.intersection(endBox) | ||
} | ||
|
||
/** | ||
* Calculates all positions for this cuboid region. | ||
*/ | ||
private fun computePositions(): Set<BlockPos> { | ||
return iterateBoxBlockPositions(box).toSet() | ||
} | ||
|
||
companion object { | ||
/** | ||
* The codec of a cuboid region. | ||
*/ | ||
val CODEC: Codec<CuboidRegion> = RecordCodecBuilder.create { instance -> | ||
instance.group( | ||
Vec3d.CODEC.fieldOf("root_position").forGetter(CuboidRegion::rootPosition), | ||
Vec3d.CODEC.fieldOf("size").forGetter(CuboidRegion::size) | ||
).apply(instance, ::CuboidRegion) | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/main/kotlin/net/mcbrawls/blueprint/region/PointRegion.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package net.mcbrawls.blueprint.region | ||
|
||
import com.mojang.serialization.Codec | ||
import com.mojang.serialization.codecs.RecordCodecBuilder | ||
import net.mcbrawls.blueprint.region.serialization.SerializableRegion | ||
import net.mcbrawls.blueprint.region.serialization.SerializableRegionTypes | ||
import net.minecraft.entity.Entity | ||
import net.minecraft.util.math.BlockPos | ||
|
||
/** | ||
* A region defined by a single point in the world. | ||
* Useful for cases such as respawn or chest positions. | ||
*/ | ||
data class PointRegion( | ||
/** | ||
* The position of the point. | ||
*/ | ||
val position: BlockPos | ||
) : SerializableRegion(SerializableRegionTypes.POINT) { | ||
override val positions: Set<BlockPos> = setOf(position) | ||
|
||
/** | ||
* A predicate to check if an entity is at the point position. | ||
*/ | ||
override fun contains(entity: Entity): Boolean { | ||
return entity.blockPos.equals(position) | ||
} | ||
|
||
companion object { | ||
/** | ||
* The codec of a cuboid region. | ||
*/ | ||
val CODEC: Codec<PointRegion> = RecordCodecBuilder.create { instance -> | ||
instance.group( | ||
BlockPos.CODEC.fieldOf("position").forGetter(PointRegion::position), | ||
).apply(instance, ::PointRegion) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package net.mcbrawls.blueprint.region | ||
|
||
import net.minecraft.entity.Entity | ||
import net.minecraft.util.math.BlockPos | ||
import net.minecraft.util.math.Box | ||
|
||
/** | ||
* A region is a defined volume of space within a blueprint. | ||
*/ | ||
interface Region { | ||
/** | ||
* All positions stored within this region. | ||
*/ | ||
val positions: Set<BlockPos> | ||
|
||
/** | ||
* A predicate to check if an entity is within the region. | ||
*/ | ||
fun contains(entity: Entity): Boolean | ||
|
||
/** | ||
* Loops through each position in the region and performs the given action. | ||
*/ | ||
fun forEachPosition(action: (BlockPos) -> Unit) { | ||
positions.forEach(action) | ||
} | ||
|
||
companion object { | ||
/** | ||
* Creates an iterable from a box. | ||
* @return a block position iterator | ||
*/ | ||
fun iterateBoxBlockPositions(box: Box): Iterable<BlockPos> { | ||
val minX = box.minX.toInt() | ||
val minY = box.minY.toInt() | ||
val minZ = box.minZ.toInt() | ||
val maxX = box.maxX.toInt() | ||
val maxY = box.maxY.toInt() | ||
val maxZ = box.maxZ.toInt() | ||
return BlockPos.iterate(minX, minY, minZ, maxX, maxY, maxZ) | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
src/main/kotlin/net/mcbrawls/blueprint/region/SphericalRegion.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package net.mcbrawls.blueprint.region | ||
|
||
import com.mojang.serialization.Codec | ||
import com.mojang.serialization.codecs.RecordCodecBuilder | ||
import net.mcbrawls.blueprint.region.Region.Companion.iterateBoxBlockPositions | ||
import net.mcbrawls.blueprint.region.serialization.SerializableRegion | ||
import net.mcbrawls.blueprint.region.serialization.SerializableRegionTypes | ||
import net.minecraft.entity.Entity | ||
import net.minecraft.util.math.BlockPos | ||
import net.minecraft.util.math.Box | ||
import net.minecraft.util.math.Vec3d | ||
|
||
// TODO: test: see if radii need squaring | ||
|
||
/** | ||
* A region defined by a sphere. | ||
*/ | ||
data class SphericalRegion( | ||
/** | ||
* The root position of the region. | ||
*/ | ||
val rootPosition: Vec3d, | ||
|
||
/** | ||
* The radius of the sphere, expanding from the root position. | ||
*/ | ||
val radius: Double | ||
) : SerializableRegion(SerializableRegionTypes.SPHERE) { | ||
override val positions: Set<BlockPos> = computePositions() | ||
|
||
override fun contains(entity: Entity): Boolean { | ||
return entity.squaredDistanceTo(rootPosition) <= radius | ||
} | ||
|
||
/** | ||
* Calculates all positions for this spherical region. | ||
*/ | ||
private fun computePositions(): Set<BlockPos> { | ||
// create box | ||
val diameter = radius * 2 | ||
val box = Box.of(rootPosition, diameter, diameter, diameter) | ||
|
||
// iterate through all positions and find all that are within range for a sphere | ||
val boxPositions = iterateBoxBlockPositions(box) | ||
return boxPositions.filter(::isPositionWithinRadius).toSet() | ||
} | ||
|
||
private fun isPositionWithinRadius(position: BlockPos): Boolean { | ||
return position.getSquaredDistance(rootPosition) <= radius | ||
} | ||
|
||
companion object { | ||
/** | ||
* The codec of a spherical region. | ||
*/ | ||
val CODEC: Codec<SphericalRegion> = RecordCodecBuilder.create { instance -> | ||
instance.group( | ||
Vec3d.CODEC.fieldOf("root_position").forGetter(SphericalRegion::rootPosition), | ||
Codec.DOUBLE.fieldOf("radius").forGetter(SphericalRegion::radius) | ||
).apply(instance, ::SphericalRegion) | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/main/kotlin/net/mcbrawls/blueprint/region/serialization/SerializableRegion.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package net.mcbrawls.blueprint.region.serialization | ||
|
||
import com.mojang.serialization.Codec | ||
import net.mcbrawls.blueprint.region.Region | ||
|
||
/** | ||
* A region which can be serialized or deserialized by codecs. | ||
*/ | ||
abstract class SerializableRegion( | ||
/** | ||
* The serialized type of this region. | ||
*/ | ||
val type: SerializableRegionType | ||
) : Region { | ||
companion object { | ||
/** | ||
* The codec for a serializable region, defined by its type. | ||
*/ | ||
val CODEC: Codec<SerializableRegion> = SerializableRegionTypes.REGISTRY.getCodec() | ||
.dispatch("type", SerializableRegion::type, SerializableRegionType::codec) | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/kotlin/net/mcbrawls/blueprint/region/serialization/SerializableRegionType.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package net.mcbrawls.blueprint.region.serialization | ||
|
||
import com.mojang.serialization.Codec | ||
|
||
/** | ||
* A type of serializable region. | ||
*/ | ||
data class SerializableRegionType( | ||
/** | ||
* The codec of this serializable region type. | ||
*/ | ||
val codec: Codec<out SerializableRegion> | ||
) |
32 changes: 32 additions & 0 deletions
32
src/main/kotlin/net/mcbrawls/blueprint/region/serialization/SerializableRegionTypes.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package net.mcbrawls.blueprint.region.serialization | ||
|
||
import com.mojang.serialization.Lifecycle | ||
import net.mcbrawls.blueprint.BlueprintMod | ||
import net.mcbrawls.blueprint.region.CuboidRegion | ||
import net.mcbrawls.blueprint.region.PointRegion | ||
import net.mcbrawls.blueprint.region.SphericalRegion | ||
import net.minecraft.registry.Registry | ||
import net.minecraft.registry.RegistryKey | ||
import net.minecraft.registry.SimpleRegistry | ||
import net.minecraft.util.Identifier | ||
|
||
object SerializableRegionTypes { | ||
/** | ||
* The registry key for serializable region types. | ||
*/ | ||
val REGISTRY_KEY: RegistryKey<Registry<SerializableRegionType>> = | ||
RegistryKey.ofRegistry(Identifier(BlueprintMod.MOD_ID, "serializable_region_types")) | ||
|
||
/** | ||
* The registry of serializable region types. | ||
*/ | ||
val REGISTRY: Registry<SerializableRegionType> = SimpleRegistry(REGISTRY_KEY, Lifecycle.stable()) | ||
|
||
val POINT = register("point", SerializableRegionType(PointRegion.CODEC)) | ||
val CUBOID = register("cuboid", SerializableRegionType(CuboidRegion.CODEC)) | ||
val SPHERE = register("sphere", SerializableRegionType(SphericalRegion.CODEC)) | ||
|
||
private fun register(id: String, type: SerializableRegionType): SerializableRegionType { | ||
return Registry.register(REGISTRY, Identifier(BlueprintMod.MOD_ID, id), type) | ||
} | ||
} |