1
0
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:
chylex 2018-12-30 06:37:38 +01:00
parent 15caa41c38
commit 307ebe0643
5 changed files with 231 additions and 4 deletions
src/main/java/chylex/hee/game/mechanics/instability

View File

@ -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)))
}
}

View File

@ -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))
}
}
}

View File

@ -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) }
}
}

View File

@ -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 }
}
}

View File

@ -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)
}
}*/
}