mirror of
https://github.com/chylex/Hardcore-Ender-Expansion-2.git
synced 2025-04-11 03:15:44 +02:00
Finish implementing dimension & region instability for all dimensions
This commit is contained in:
parent
15caa41c38
commit
307ebe0643
src/main/java/chylex/hee/game/mechanics/instability
@ -1,15 +1,19 @@
|
||||
package chylex.hee.game.mechanics.instability
|
||||
import chylex.hee.game.mechanics.instability.Instability.InstabilityCapability.Provider
|
||||
import chylex.hee.game.mechanics.instability.dimension.DimensionInstabilityEndTerritory
|
||||
import chylex.hee.game.mechanics.instability.dimension.DimensionInstabilityGlobal
|
||||
import chylex.hee.game.mechanics.instability.dimension.DimensionInstabilityNull
|
||||
import chylex.hee.game.mechanics.instability.dimension.IDimensionInstability
|
||||
import chylex.hee.game.mechanics.instability.dimension.components.EndermiteSpawnLogicOverworld
|
||||
import chylex.hee.game.mechanics.instability.region.RegionInstability
|
||||
import chylex.hee.game.mechanics.instability.region.entry.types.Entry5x5
|
||||
import chylex.hee.system.Resource
|
||||
import chylex.hee.system.util.forge.capabilities.CapabilityProvider
|
||||
import chylex.hee.system.util.forge.capabilities.NullFactory
|
||||
import chylex.hee.system.util.forge.capabilities.NullStorage
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldProviderSurface
|
||||
import net.minecraft.world.WorldProviderEnd
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.common.capabilities.Capability
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject
|
||||
@ -17,7 +21,7 @@ import net.minecraftforge.common.capabilities.CapabilityManager
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase.START
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent.WorldTickEvent
|
||||
|
||||
object Instability{
|
||||
@ -34,7 +38,7 @@ object Instability{
|
||||
|
||||
@SubscribeEvent
|
||||
fun onWorldTick(e: WorldTickEvent){
|
||||
if (e.phase == START){
|
||||
if (e.phase == Phase.START){
|
||||
e.world.getCapability(CAP_INSTABILITY!!, null)?.region?.update()
|
||||
}
|
||||
}
|
||||
@ -52,7 +56,11 @@ object Instability{
|
||||
val world = e.`object`
|
||||
|
||||
when(world.provider){
|
||||
// TODO
|
||||
is WorldProviderEnd ->
|
||||
e.addCapability(CAP_KEY, Provider(DimensionInstabilityEndTerritory(world), RegionInstability(world, Entry5x5.Constructor)))
|
||||
|
||||
else ->
|
||||
e.addCapability(CAP_KEY, Provider(DimensionInstabilityGlobal(world, EndermiteSpawnLogicOverworld), RegionInstability(world, Entry5x5.Constructor)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,43 @@
|
||||
package chylex.hee.game.mechanics.instability.dimension
|
||||
import chylex.hee.game.mechanics.instability.dimension.components.EndermiteSpawnLogicEndTerritory
|
||||
import chylex.hee.game.world.territory.TerritoryInstance
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
class DimensionInstabilityEndTerritory(private val world: World) : IDimensionInstability{
|
||||
private val territories = Int2ObjectOpenHashMap<DimensionInstabilityGlobal>()
|
||||
|
||||
private fun putEntry(key: Int): DimensionInstabilityGlobal{
|
||||
return DimensionInstabilityGlobal(world, EndermiteSpawnLogicEndTerritory).also { territories[key] = it }
|
||||
}
|
||||
|
||||
private fun getEntry(pos: BlockPos): IDimensionInstability{
|
||||
val instance = TerritoryInstance.fromPos(pos) ?: return DimensionInstabilityNull
|
||||
val key = instance.hash
|
||||
|
||||
return territories[key] ?: putEntry(key)
|
||||
}
|
||||
|
||||
override fun triggerAction(amount: UShort, pos: BlockPos){
|
||||
getEntry(pos).triggerAction(amount, pos)
|
||||
}
|
||||
|
||||
override fun triggerRelief(amount: UShort, pos: BlockPos){
|
||||
getEntry(pos).triggerRelief(amount, pos)
|
||||
}
|
||||
|
||||
override fun serializeNBT() = NBTTagCompound().apply {
|
||||
for(entry in territories.int2ObjectEntrySet()){
|
||||
setTag(entry.intKey.toString(), entry.value.serializeNBT())
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: NBTTagCompound){
|
||||
for(key in nbt.keySet){
|
||||
val keyInt = key.toIntOrNull() ?: continue
|
||||
putEntry(keyInt).deserializeNBT(nbt.getCompoundTag(key))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package chylex.hee.game.mechanics.instability.dimension.components
|
||||
import chylex.hee.game.entity.living.EntityMobEndermiteInstability
|
||||
import chylex.hee.game.world.territory.TerritoryInstance
|
||||
import net.minecraft.entity.monster.IMob
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
object EndermiteSpawnLogicEndTerritory : EndermiteSpawnLogic(){
|
||||
override fun checkMobLimits(world: World, pos: BlockPos): Boolean{
|
||||
val instance = TerritoryInstance.fromPos(pos)
|
||||
|
||||
var hostileMobCount = 0
|
||||
var endermiteCount = 0
|
||||
|
||||
for(entity in world.loadedEntityList){
|
||||
if (entity is IMob){
|
||||
if (++hostileMobCount > 150){
|
||||
return false
|
||||
}
|
||||
|
||||
if (entity is EntityMobEndermiteInstability && instance == TerritoryInstance.fromPos(entity) && ++endermiteCount > 24){
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun countExisting(world: World, pos: BlockPos): Int{
|
||||
val instance = TerritoryInstance.fromPos(pos)
|
||||
return world.loadedEntityList.count { it is EntityMobEndermiteInstability && instance == TerritoryInstance.fromPos(it) }
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package chylex.hee.game.mechanics.instability.dimension.components
|
||||
import chylex.hee.game.entity.living.EntityMobEndermiteInstability
|
||||
import net.minecraft.entity.monster.IMob
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
object EndermiteSpawnLogicOverworld : EndermiteSpawnLogic(){
|
||||
override fun checkMobLimits(world: World, pos: BlockPos): Boolean{
|
||||
var hostileMobCount = 0
|
||||
var endermiteCount = 0
|
||||
|
||||
for(entity in world.loadedEntityList){
|
||||
if (entity is IMob){
|
||||
if (++hostileMobCount > 150){
|
||||
return false
|
||||
}
|
||||
|
||||
if (entity is EntityMobEndermiteInstability && ++endermiteCount > 40){
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun countExisting(world: World, pos: BlockPos): Int{
|
||||
return world.loadedEntityList.count { it is EntityMobEndermiteInstability }
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package chylex.hee.game.mechanics.instability.region.entry.types
|
||||
import chylex.hee.game.mechanics.instability.region.entry.IRegionEntry
|
||||
import chylex.hee.game.mechanics.instability.region.entry.IRegionEntryConstructor
|
||||
import chylex.hee.system.util.shlong
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
inline class Entry5x5(override val compacted: Long) : IRegionEntry{
|
||||
private companion object{
|
||||
private const val MASK_X = 0x00000_FFFFFL
|
||||
private const val MASK_Z = 0xFFFFF_00000L
|
||||
private const val MASK_XZ = MASK_X or MASK_Z
|
||||
|
||||
private const val BIT_OFFSET_X = 0
|
||||
private const val BIT_OFFSET_Z = 20
|
||||
private const val BIT_OFFSET_POINTS = 40
|
||||
|
||||
private const val REGION_CHUNKS = 5
|
||||
private const val REGION_BLOCKS = REGION_CHUNKS * 16
|
||||
private const val REGION_Z_OFFSET_BLOCKS = REGION_BLOCKS / 2
|
||||
|
||||
// methods must be public, otherwise some weird interaction between them and inline classes generates invalid bytecode
|
||||
|
||||
fun fromRegion(regionX: Int, regionZ: Int): Entry5x5{
|
||||
val bitsX = (regionX shlong BIT_OFFSET_X) and MASK_X
|
||||
val bitsZ = (regionZ shlong BIT_OFFSET_Z) and MASK_Z
|
||||
|
||||
return Entry5x5(bitsX or bitsZ)
|
||||
}
|
||||
|
||||
fun fixNegativeCoord(coord: Int): Int{
|
||||
return if (coord > 0x7FFFF)
|
||||
-(0xFFFFF - coord)
|
||||
else
|
||||
coord
|
||||
}
|
||||
}
|
||||
|
||||
object Constructor : IRegionEntryConstructor<Entry5x5>{
|
||||
override fun fromCompacted(compacted: Long): Entry5x5{
|
||||
return Entry5x5(compacted)
|
||||
}
|
||||
|
||||
override fun fromPos(pos: BlockPos): Entry5x5{
|
||||
val regionX = getRegionCoord(pos.x)
|
||||
|
||||
val offsetZ = if (regionX % 2 == 0) 0 else REGION_Z_OFFSET_BLOCKS
|
||||
val regionZ = getRegionCoord(pos.z + offsetZ)
|
||||
|
||||
return fromRegion(regionX, regionZ)
|
||||
}
|
||||
|
||||
private inline fun getRegionCoord(coord: Int): Int{
|
||||
return if (coord < 0)
|
||||
((coord + 1) / REGION_BLOCKS) - 1
|
||||
else
|
||||
coord / REGION_BLOCKS
|
||||
}
|
||||
}
|
||||
|
||||
// Instance
|
||||
|
||||
override val key
|
||||
get() = compacted and MASK_XZ
|
||||
|
||||
override val x
|
||||
get() = ((compacted and MASK_X) ushr BIT_OFFSET_X).toInt()
|
||||
|
||||
override val z
|
||||
get() = ((compacted and MASK_Z) ushr BIT_OFFSET_Z).toInt()
|
||||
|
||||
override val points
|
||||
get() = (compacted shr BIT_OFFSET_POINTS).toInt()
|
||||
|
||||
override val adjacent: Sequence<Entry5x5>
|
||||
get(){
|
||||
val x = this.x
|
||||
val z = this.z
|
||||
|
||||
val offsetZ = x and 1
|
||||
|
||||
return sequenceOf(
|
||||
fromRegion(x + 0, z - 1),
|
||||
fromRegion(x + 0, z + 1),
|
||||
fromRegion(x - 1, z + 0 - offsetZ),
|
||||
fromRegion(x + 1, z + 0 - offsetZ),
|
||||
fromRegion(x - 1, z + 1 - offsetZ),
|
||||
fromRegion(x + 1, z + 1 - offsetZ)
|
||||
)
|
||||
}
|
||||
|
||||
override fun withPoints(points: Int): Entry5x5{
|
||||
return Entry5x5((compacted and MASK_XZ) or (points shlong BIT_OFFSET_POINTS))
|
||||
}
|
||||
|
||||
override fun toString(): String{
|
||||
return "Entry5x5 (x = ${fixNegativeCoord(x)}, z = ${fixNegativeCoord(z)}, points = $points, key = $key, compacted = $compacted)"
|
||||
}
|
||||
|
||||
/* why write tests when you can plop this into the code and see what it does with your eyes
|
||||
|
||||
Pos(0, 16, 0).allInCenteredBoxMutable(200, 0, 200).forEach { pos ->
|
||||
val e = Entry5x5.Constructor.fromPos(pos)
|
||||
pos.setState(world, Blocks.WOOL.defaultState.withProperty(COLOR, EnumDyeColor.values()[(e.x + 4 * e.z) % 16]))
|
||||
|
||||
if (Entry5x5.Constructor.fromPos(Pos(0, 0, 0)).adjacent.any { it.key == e.key }){
|
||||
pos.up().setBlock(world, Blocks.ACACIA_FENCE)
|
||||
}
|
||||
else{
|
||||
pos.up().setAir(world)
|
||||
}
|
||||
}*/
|
||||
}
|
Loading…
Reference in New Issue
Block a user