mirror of
https://github.com/chylex/Hardcore-Ender-Expansion-2.git
synced 2025-04-11 03:15:44 +02:00
Implement territory storage component and ticking system & store Token type
This commit is contained in:
parent
284779bb64
commit
86c0b6a0ec
src/main/java/chylex/hee
@ -96,7 +96,7 @@ class ItemPortalToken(properties: Properties) : Item(properties){
|
||||
val territory = getTerritoryType(stack) ?: return null
|
||||
|
||||
val index = with(stack.heeTag){
|
||||
getIntegerOrNull(TERRITORY_INDEX_TAG) ?: TerritoryGlobalStorage.get().assignNewIndex(territory).also { putInt(TERRITORY_INDEX_TAG, it) }
|
||||
getIntegerOrNull(TERRITORY_INDEX_TAG) ?: TerritoryGlobalStorage.get().assignNewIndex(territory, getTokenType(stack)).also { putInt(TERRITORY_INDEX_TAG, it) }
|
||||
}
|
||||
|
||||
return TerritoryInstance(territory, index)
|
||||
@ -112,7 +112,7 @@ class ItemPortalToken(properties: Properties) : Item(properties){
|
||||
return super.onItemRightClick(world, player, hand)
|
||||
}
|
||||
|
||||
val index = heldItem.heeTagOrNull?.getIntegerOrNull(TERRITORY_INDEX_TAG) ?: TerritoryGlobalStorage.get().assignNewIndex(territory)
|
||||
val index = heldItem.heeTagOrNull?.getIntegerOrNull(TERRITORY_INDEX_TAG) ?: TerritoryGlobalStorage.get().assignNewIndex(territory, getTokenType(heldItem))
|
||||
val instance = TerritoryInstance(territory, index)
|
||||
|
||||
if (!EntityPortalContact.shouldTeleport(player)){
|
||||
|
@ -10,6 +10,7 @@ import chylex.hee.game.world.provider.DragonFightManagerNull
|
||||
import chylex.hee.game.world.provider.WorldBorderNull
|
||||
import chylex.hee.game.world.territory.TerritoryInstance
|
||||
import chylex.hee.game.world.territory.TerritoryInstance.Companion.THE_HUB_INSTANCE
|
||||
import chylex.hee.game.world.territory.TerritoryTicker
|
||||
import chylex.hee.game.world.territory.TerritoryVoid
|
||||
import chylex.hee.proxy.ISidedProxy
|
||||
import chylex.hee.system.forge.EventPriority
|
||||
@ -77,6 +78,9 @@ class WorldProviderEndCustom(world: World, type: DimensionType) : EndDimension(w
|
||||
private val clientEnvironment
|
||||
get() = clientProxy?.getClientSidePlayer()?.let(TerritoryInstance.Companion::fromPos)?.let { it.territory.desc.environment }
|
||||
|
||||
private val serverWorld
|
||||
get() = world as ServerWorld
|
||||
|
||||
init{
|
||||
when(val w = this.world){
|
||||
is ServerWorld -> {
|
||||
@ -124,8 +128,10 @@ class WorldProviderEndCustom(world: World, type: DimensionType) : EndDimension(w
|
||||
// Behavior properties
|
||||
|
||||
override fun tick(){ // stops triggering a few seconds after all players leave the dimension (if still loaded)
|
||||
TerritoryTicker.onWorldTick(serverWorld)
|
||||
|
||||
if (!debugMode){
|
||||
TerritoryVoid.onWorldTick(world as ServerWorld)
|
||||
TerritoryVoid.onWorldTick(serverWorld)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package chylex.hee.game.world.territory
|
||||
import chylex.hee.game.world.territory.properties.TerritoryColors
|
||||
import chylex.hee.game.world.territory.properties.TerritoryEnvironment
|
||||
import chylex.hee.game.world.territory.properties.TerritoryTokenHolders
|
||||
import chylex.hee.game.world.territory.storage.TerritoryEntry
|
||||
|
||||
interface ITerritoryDescription{
|
||||
val colors: TerritoryColors
|
||||
@ -10,4 +11,8 @@ interface ITerritoryDescription{
|
||||
@JvmDefault
|
||||
val tokenHolders: TerritoryTokenHolders
|
||||
get() = TerritoryTokenHolders.Default
|
||||
|
||||
@JvmDefault
|
||||
fun initialize(instance: TerritoryInstance, entry: TerritoryEntry, tickers: MutableList<ITerritoryTicker>){
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package chylex.hee.game.world.territory
|
||||
import net.minecraft.world.World
|
||||
|
||||
interface ITerritoryTicker{
|
||||
/**
|
||||
* If this value matches the current world tick, all players inside the ticker's territory will be sent a new [chylex.hee.network.client.PacketClientTerritoryEnvironment].
|
||||
*/
|
||||
@JvmDefault
|
||||
val resendClientEnvironmentPacketOnWorldTick: Long
|
||||
get() = Long.MIN_VALUE
|
||||
|
||||
fun tick(world: World)
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package chylex.hee.game.world.territory
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.game.world.territory.storage.TerritoryGlobalStorage
|
||||
import chylex.hee.game.world.totalTime
|
||||
import chylex.hee.network.client.PacketClientTerritoryEnvironment
|
||||
import chylex.hee.system.forge.EventPriority
|
||||
import chylex.hee.system.forge.SubscribeAllEvents
|
||||
import chylex.hee.system.forge.SubscribeEvent
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerChangedDimensionEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedOutEvent
|
||||
import net.minecraftforge.event.world.WorldEvent
|
||||
import java.util.UUID
|
||||
|
||||
@SubscribeAllEvents(modid = HEE.ID)
|
||||
object TerritoryTicker{
|
||||
private val active = mutableMapOf<TerritoryInstance, Entry>()
|
||||
private val lastTerritory = mutableMapOf<UUID, TerritoryInstance>()
|
||||
|
||||
private class Entry(val tickers: List<ITerritoryTicker>){
|
||||
var lastTickTime = -1L
|
||||
}
|
||||
|
||||
fun onWorldTick(world: World){
|
||||
val currentTime = world.totalTime
|
||||
|
||||
if (currentTime % 600L == 0L){
|
||||
active.values.removeAll { currentTime - it.lastTickTime > 1L }
|
||||
}
|
||||
|
||||
for(player in world.players){
|
||||
val instance = TerritoryInstance.fromPos(player)
|
||||
|
||||
if (instance == null){
|
||||
lastTerritory.remove(player.uniqueID)
|
||||
continue
|
||||
}
|
||||
|
||||
val storage = TerritoryGlobalStorage.get().forInstance(instance)
|
||||
|
||||
if (storage == null){
|
||||
continue
|
||||
}
|
||||
|
||||
val entry = active.getOrPut(instance){
|
||||
Entry(mutableListOf<ITerritoryTicker>().also {
|
||||
instance.territory.desc.initialize(instance, storage, it)
|
||||
})
|
||||
}
|
||||
|
||||
if (entry.lastTickTime != currentTime){
|
||||
entry.lastTickTime = currentTime
|
||||
entry.tickers.forEach { it.tick(world) }
|
||||
}
|
||||
|
||||
if (instance != lastTerritory.put(player.uniqueID, instance) || entry.tickers.any { it.resendClientEnvironmentPacketOnWorldTick == currentTime }){
|
||||
PacketClientTerritoryEnvironment(storage).sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onWorldSave(e: WorldEvent.Save){
|
||||
if (e.world.dimension.type !== HEE.dim){
|
||||
return
|
||||
}
|
||||
|
||||
active.clear()
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
fun onPlayerChangedDimension(e: PlayerChangedDimensionEvent){
|
||||
if (e.to !== HEE.dim){
|
||||
lastTerritory.remove(e.player.uniqueID)
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
fun onPlayerLoggedOut(e: PlayerLoggedOutEvent){
|
||||
lastTerritory.remove(e.player.uniqueID)
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
package chylex.hee.game.world.territory.storage
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.game.item.ItemPortalToken.TokenType
|
||||
import chylex.hee.game.world.ChunkGeneratorEndCustom
|
||||
import chylex.hee.game.world.Pos
|
||||
import chylex.hee.game.world.center
|
||||
@ -7,28 +9,40 @@ import chylex.hee.system.delegate.NotifyOnChange
|
||||
import chylex.hee.system.math.toYaw
|
||||
import chylex.hee.system.migration.EntityPlayer
|
||||
import chylex.hee.system.serialization.TagCompound
|
||||
import chylex.hee.system.serialization.getCompoundOrNull
|
||||
import chylex.hee.system.serialization.getEnum
|
||||
import chylex.hee.system.serialization.getLongArrayOrNull
|
||||
import chylex.hee.system.serialization.getPosOrNull
|
||||
import chylex.hee.system.serialization.putEnum
|
||||
import chylex.hee.system.serialization.putPos
|
||||
import chylex.hee.system.serialization.use
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
import java.util.UUID
|
||||
|
||||
class TerritoryEntry(private val owner: TerritoryGlobalStorage, private val instance: TerritoryInstance) : INBTSerializable<TagCompound>{
|
||||
private companion object{
|
||||
class TerritoryEntry(private val owner: TerritoryGlobalStorage, private val instance: TerritoryInstance, val type: TokenType) : INBTSerializable<TagCompound>{
|
||||
companion object{
|
||||
private const val TYPE_TAG = "Type"
|
||||
private const val SPAWN_POINT_TAG = "Spawn"
|
||||
private const val INTEREST_POINT_TAG = "Interest"
|
||||
private const val LAST_PORTALS_TAG = "LastPortals"
|
||||
private const val COMPONENTS_TAG = "Components"
|
||||
|
||||
fun fromTag(owner: TerritoryGlobalStorage, instance: TerritoryInstance, tag: TagCompound): TerritoryEntry{
|
||||
return TerritoryEntry(owner, instance, tag.getEnum<TokenType>(TYPE_TAG) ?: TokenType.NORMAL).also { it.deserializeNBT(tag) }
|
||||
}
|
||||
}
|
||||
|
||||
private var spawnPoint: BlockPos? by NotifyOnChange(null, owner::markDirty)
|
||||
private var interestPoint: BlockPos? by NotifyOnChange(null, owner::markDirty)
|
||||
val markDirty = owner::markDirty
|
||||
|
||||
private var spawnPoint: BlockPos? by NotifyOnChange(null, markDirty)
|
||||
private var interestPoint: BlockPos? by NotifyOnChange(null, markDirty)
|
||||
|
||||
val spawnYaw
|
||||
get() = interestPoint?.center?.let { ip -> spawnPoint?.center?.let { sp -> ip.subtract(sp).toYaw() } }
|
||||
|
||||
private val lastPortals = mutableMapOf<UUID, BlockPos>()
|
||||
private val components = mutableMapOf<Class<out TerritoryStorageComponent>, TerritoryStorageComponent>()
|
||||
|
||||
fun loadSpawn(): BlockPos{
|
||||
if (spawnPoint == null){
|
||||
@ -59,7 +73,25 @@ class TerritoryEntry(private val owner: TerritoryGlobalStorage, private val inst
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : TerritoryStorageComponent> registerComponent(info: Pair<Class<T>, String>): T{
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return components.getOrPut(info.first){ TerritoryStorageComponent.getComponentConstructor(info.second)!!(markDirty) } as T
|
||||
}
|
||||
|
||||
fun <T : TerritoryStorageComponent> getComponent(cls: Class<T>): T?{
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return components[cls]?.let { it as T }
|
||||
}
|
||||
|
||||
inline fun <reified T : TerritoryStorageComponent> getComponent(): T?{
|
||||
return getComponent(T::class.java)
|
||||
}
|
||||
|
||||
override fun serializeNBT() = TagCompound().apply {
|
||||
if (this@TerritoryEntry.type != TokenType.NORMAL){
|
||||
putEnum(TYPE_TAG, this@TerritoryEntry.type)
|
||||
}
|
||||
|
||||
spawnPoint?.let {
|
||||
putPos(SPAWN_POINT_TAG, it)
|
||||
}
|
||||
@ -82,6 +114,23 @@ class TerritoryEntry(private val owner: TerritoryGlobalStorage, private val inst
|
||||
|
||||
putLongArray(LAST_PORTALS_TAG, lastPortalArray)
|
||||
}
|
||||
|
||||
if (components.isNotEmpty()){
|
||||
val componentTag = TagCompound()
|
||||
|
||||
for(component in components.values){
|
||||
val name = TerritoryStorageComponent.getComponentName(component)
|
||||
|
||||
if (name == null){
|
||||
HEE.log.error("[TerritoryEntry] could not map storage component ${component.javaClass.name} to its name")
|
||||
}
|
||||
else{
|
||||
componentTag.put(name, component.serializeNBT())
|
||||
}
|
||||
}
|
||||
|
||||
put(COMPONENTS_TAG, componentTag)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: TagCompound) = nbt.use {
|
||||
@ -97,5 +146,23 @@ class TerritoryEntry(private val owner: TerritoryGlobalStorage, private val inst
|
||||
lastPortals[UUID(lastPortalArray[index + 0], lastPortalArray[index + 1])] = Pos(lastPortalArray[2])
|
||||
}
|
||||
}
|
||||
|
||||
components.clear()
|
||||
|
||||
val componentTag = getCompoundOrNull(COMPONENTS_TAG)
|
||||
|
||||
if (componentTag != null){
|
||||
for(name in componentTag.keySet()){
|
||||
val constructor = TerritoryStorageComponent.getComponentConstructor(name)
|
||||
|
||||
if (constructor == null){
|
||||
HEE.log.error("[TerritoryEntry] could not map storage component name $name to its constructor")
|
||||
}
|
||||
else{
|
||||
val component = constructor(markDirty).also { it.deserializeNBT(componentTag.getCompound(name)) }
|
||||
components[component.javaClass] = component
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
package chylex.hee.game.world.territory.storage
|
||||
import chylex.hee.game.item.ItemPortalToken.TokenType
|
||||
import chylex.hee.game.world.perDimensionData
|
||||
import chylex.hee.game.world.territory.TerritoryInstance
|
||||
import chylex.hee.game.world.territory.TerritoryInstance.Companion.THE_HUB_INSTANCE
|
||||
@ -20,14 +21,18 @@ class TerritoryGlobalStorage private constructor() : WorldSavedData(NAME){
|
||||
|
||||
// Instance
|
||||
|
||||
private val spawnEntry = TerritoryEntry(this, THE_HUB_INSTANCE)
|
||||
private val spawnEntry = TerritoryEntry(this, THE_HUB_INSTANCE, TokenType.NORMAL)
|
||||
private val territoryData = EnumMap(TerritoryType.values().filterNot { it.isSpawn }.associateWith { mutableListOf<TerritoryEntry>() })
|
||||
|
||||
private fun makeEntry(territory: TerritoryType, index: Int): TerritoryEntry{
|
||||
return TerritoryEntry(this, TerritoryInstance(territory, index))
|
||||
private fun makeEntry(territory: TerritoryType, index: Int, type: TokenType): TerritoryEntry{
|
||||
return TerritoryEntry(this, TerritoryInstance(territory, index), type)
|
||||
}
|
||||
|
||||
fun assignNewIndex(territory: TerritoryType): Int{
|
||||
private fun makeEntry(territory: TerritoryType, index: Int, tag: TagCompound): TerritoryEntry{
|
||||
return TerritoryEntry.fromTag(this, TerritoryInstance(territory, index), tag)
|
||||
}
|
||||
|
||||
fun assignNewIndex(territory: TerritoryType, tokenType: TokenType): Int{
|
||||
if (territory.isSpawn){
|
||||
return 0
|
||||
}
|
||||
@ -35,7 +40,7 @@ class TerritoryGlobalStorage private constructor() : WorldSavedData(NAME){
|
||||
val list = territoryData.getValue(territory)
|
||||
val newIndex = list.size
|
||||
|
||||
list.add(makeEntry(territory, newIndex))
|
||||
list.add(makeEntry(territory, newIndex, tokenType))
|
||||
markDirty()
|
||||
|
||||
return newIndex
|
||||
@ -68,7 +73,7 @@ class TerritoryGlobalStorage private constructor() : WorldSavedData(NAME){
|
||||
val list = territoryData.getValue(territory)
|
||||
|
||||
list.clear()
|
||||
list.addAll(getListOfCompounds(key).mapIndexed { index, nbt -> makeEntry(territory, index).also { it.deserializeNBT(nbt) } })
|
||||
list.addAll(getListOfCompounds(key).mapIndexed { index, nbt -> makeEntry(territory, index, nbt) })
|
||||
}
|
||||
|
||||
isDirty = false
|
||||
|
@ -0,0 +1,21 @@
|
||||
package chylex.hee.game.world.territory.storage
|
||||
import chylex.hee.system.serialization.TagCompound
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
|
||||
abstract class TerritoryStorageComponent : INBTSerializable<TagCompound>{
|
||||
companion object{
|
||||
private val CLASS_TO_STRING = mapOf<Class<out TerritoryStorageComponent>, String>(
|
||||
)
|
||||
|
||||
private val STRING_TO_INSTANCE = mapOf<String, (() -> Unit) -> TerritoryStorageComponent>(
|
||||
)
|
||||
|
||||
fun getComponentName(component: TerritoryStorageComponent): String?{
|
||||
return CLASS_TO_STRING[component.javaClass]
|
||||
}
|
||||
|
||||
fun getComponentConstructor(name: String): ((() -> Unit) -> TerritoryStorageComponent)?{
|
||||
return STRING_TO_INSTANCE[name]
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import chylex.hee.network.client.PacketClientMoveYourAss
|
||||
import chylex.hee.network.client.PacketClientPotionDuration
|
||||
import chylex.hee.network.client.PacketClientRotateInstantly
|
||||
import chylex.hee.network.client.PacketClientTeleportInstantly
|
||||
import chylex.hee.network.client.PacketClientTerritoryEnvironment
|
||||
import chylex.hee.network.client.PacketClientTrinketBreak
|
||||
import chylex.hee.network.client.PacketClientUpdateExperience
|
||||
import chylex.hee.network.client.PacketClientWeather
|
||||
@ -24,6 +25,7 @@ object ModPackets{
|
||||
build<PacketClientPotionDuration>(),
|
||||
build<PacketClientRotateInstantly>(),
|
||||
build<PacketClientTeleportInstantly>(),
|
||||
build<PacketClientTerritoryEnvironment>(),
|
||||
build<PacketClientTrinketBreak>(),
|
||||
build<PacketClientUpdateExperience>(),
|
||||
build<PacketClientWeather>(),
|
||||
|
@ -0,0 +1,40 @@
|
||||
package chylex.hee.network.client
|
||||
import chylex.hee.game.world.territory.storage.TerritoryEntry
|
||||
import chylex.hee.network.BaseClientPacket
|
||||
import chylex.hee.system.forge.Side
|
||||
import chylex.hee.system.forge.Sided
|
||||
import chylex.hee.system.migration.EntityPlayerSP
|
||||
import chylex.hee.system.serialization.TagCompound
|
||||
import chylex.hee.system.serialization.readTag
|
||||
import chylex.hee.system.serialization.use
|
||||
import chylex.hee.system.serialization.writeTag
|
||||
import net.minecraft.network.PacketBuffer
|
||||
|
||||
class PacketClientTerritoryEnvironment() : BaseClientPacket(){
|
||||
constructor(entry: TerritoryEntry) : this(){
|
||||
}
|
||||
|
||||
override fun write(buffer: PacketBuffer) = buffer.use {
|
||||
}
|
||||
|
||||
override fun read(buffer: PacketBuffer) = buffer.use {
|
||||
}
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
override fun handle(player: EntityPlayerSP){
|
||||
}
|
||||
|
||||
private fun PacketBuffer.writeOptionalTag(tag: TagCompound?){
|
||||
if (tag == null){
|
||||
writeBoolean(false)
|
||||
}
|
||||
else{
|
||||
writeBoolean(true)
|
||||
writeTag(tag)
|
||||
}
|
||||
}
|
||||
|
||||
private fun PacketBuffer.readOptionalTag(): TagCompound?{
|
||||
return if (readBoolean()) readTag() else null
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user